diff --git a/src/ecmascript/Makefile b/src/ecmascript/Makefile index 3bc44469..b50600d5 100644 --- a/src/ecmascript/Makefile +++ b/src/ecmascript/Makefile @@ -6,8 +6,6 @@ SUBDIRS-$(CONFIG_LIBDOM) += libdom SUBDIRS-$(CONFIG_MUJS) += mujs -SUBDIRS-$(CONFIG_QUICKJS) += quickjs - OBJS-$(CONFIG_ECMASCRIPT_SMJS) += css2xpath.obj ecmascript.obj localstorage-db.obj spidermonkey.obj timer.obj OBJS-$(CONFIG_MUJS) += css2xpath.obj ecmascript.obj localstorage-db.obj mujs.obj timer.obj diff --git a/src/ecmascript/meson.build b/src/ecmascript/meson.build index 5fced0a2..6b1db498 100644 --- a/src/ecmascript/meson.build +++ b/src/ecmascript/meson.build @@ -21,7 +21,6 @@ if conf_data.get('CONFIG_MUJS') endif if conf_data.get('CONFIG_QUICKJS') - subdir('quickjs') srcs += files('css2xpath.cpp', 'ecmascript.cpp', 'localstorage-db.cpp', 'quickjs.cpp', 'timer.cpp') endif diff --git a/src/ecmascript/quickjs/Makefile b/src/ecmascript/quickjs/Makefile deleted file mode 100644 index 4a590213..00000000 --- a/src/ecmascript/quickjs/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -top_builddir=../../.. -include $(top_builddir)/Makefile.config - -OBJS = attr.obj attributes.obj collection.obj console.obj document.obj element.obj form.obj \ - forms.obj heartbeat.obj history.obj implementation.obj input.obj keyboard.obj location.obj \ - localstorage.obj message.obj navigator.obj nodelist.obj screen.obj unibar.obj window.obj xhr.obj - -include $(top_srcdir)/Makefile.lib diff --git a/src/ecmascript/quickjs/attr.cpp b/src/ecmascript/quickjs/attr.cpp deleted file mode 100644 index 286df97d..00000000 --- a/src/ecmascript/quickjs/attr.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* The QuickJS attr object implementation. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "elinks.h" - -#include "bfu/dialog.h" -#include "cache/cache.h" -#include "cookies/cookies.h" -#include "dialogs/menu.h" -#include "dialogs/status.h" -#include "document/html/frames.h" -#include "document/document.h" -#include "document/forms.h" -#include "document/view.h" -#include "ecmascript/ecmascript.h" -#include "ecmascript/quickjs.h" -#include "ecmascript/quickjs/attr.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/memory.h" -#include "util/string.h" -#include "viewer/text/draw.h" -#include "viewer/text/form.h" -#include "viewer/text/link.h" -#include "viewer/text/vs.h" - -#include -#include -#include -#include -#include - -#include -#include -#include - -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -#ifndef CONFIG_LIBDOM - -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; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - - xmlpp::AttributeNode *attr = static_cast(JS_GetOpaque(this_val, js_attr_class_id)); - - if (!attr) { - return JS_NULL; - } - - xmlpp::ustring v = attr->get_name(); - - JSValue r = JS_NewString(ctx, v.c_str()); - - 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; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - - xmlpp::AttributeNode *attr = static_cast(JS_GetOpaque(this_val, js_attr_class_id)); - - if (!attr) { - return JS_NULL; - } - - xmlpp::ustring v = attr->get_value(); - - JSValue r = JS_NewString(ctx, v.c_str()); - - 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, nullptr), - JS_CGETSET_DEF("value", js_attr_get_property_value, nullptr), - JS_CFUNC_DEF("toString", 0, js_attr_toString) -}; - -static std::map map_attrs; - -static -void js_attr_finalizer(JSRuntime *rt, JSValue val) -{ - REF_JS(val); - void *node = JS_GetOpaque(val, js_attr_class_id); - - map_attrs.erase(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 - 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); - initialized = 1; - } - - auto node_find = map_attrs.find(node); - - if (node_find != map_attrs.end()) { - JSValue r = JS_DupValue(ctx, node_find->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); - - map_attrs[node] = attr_obj; - - JSValue rr = JS_DupValue(ctx, attr_obj); - - RETURN_JS(rr); -} -#endif diff --git a/src/ecmascript/quickjs/attributes.cpp b/src/ecmascript/quickjs/attributes.cpp deleted file mode 100644 index a729a309..00000000 --- a/src/ecmascript/quickjs/attributes.cpp +++ /dev/null @@ -1,319 +0,0 @@ -/* The QuickJS attributes object implementation. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "elinks.h" - -#include "bfu/dialog.h" -#include "cache/cache.h" -#include "cookies/cookies.h" -#include "dialogs/menu.h" -#include "dialogs/status.h" -#include "document/html/frames.h" -#include "document/document.h" -#include "document/forms.h" -#include "document/view.h" -#include "ecmascript/ecmascript.h" -#include "ecmascript/quickjs.h" -#include "ecmascript/quickjs/attr.h" -#include "ecmascript/quickjs/attributes.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/memory.h" -#include "util/string.h" -#include "viewer/text/draw.h" -#include "viewer/text/form.h" -#include "viewer/text/link.h" -#include "viewer/text/vs.h" - -#include -#include -#include -#include -#include - -#include -#include -#include - -#ifndef CONFIG_LIBDOM -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -static std::map map_attributes; -static std::map map_rev_attributes; - -static void * -js_attributes_GetOpaque(JSValueConst this_val) -{ - REF_JS(this_val); - - return map_rev_attributes[this_val]; -} - -static void -js_attributes_SetOpaque(JSValueConst this_val, void *node) -{ - REF_JS(this_val); - - if (!node) { - map_rev_attributes.erase(this_val); - } else { - map_rev_attributes[this_val] = node; - } -} - -static void -js_attributes_set_items(JSContext *ctx, JSValue this_val, void *node) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element::AttributeList *al = static_cast(node); - - if (!al) { - return; - } - - auto it = al->begin(); - auto end = al->end(); - int i = 0; - - for (;it != end; ++it, ++i) { - xmlpp::Attribute *attr = *it; - - if (!attr) { - continue; - } - - JSValue obj = getAttr(ctx, attr); - - REF_JS(obj); - - JS_SetPropertyUint32(ctx, this_val, i, JS_DupValue(ctx, obj)); - - xmlpp::ustring name = attr->get_name(); - - if (name != "" && name != "item" && name != "namedItem") { - JS_DefinePropertyValueStr(ctx, this_val, name.c_str(), JS_DupValue(ctx, obj), 0); - } - JS_FreeValue(ctx, obj); - } -} - -static JSValue -js_attributes_get_property_length(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; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - - xmlpp::Element::AttributeList *al = static_cast(js_attributes_GetOpaque(this_val)); - - if (!al) { - return JS_NewInt32(ctx, 0); - } - - return JS_NewInt32(ctx, al->size()); -} - -static JSValue -js_attributes_item2(JSContext *ctx, JSValueConst this_val, int idx) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element::AttributeList *al = static_cast(js_attributes_GetOpaque(this_val)); - - if (!al) { - return JS_UNDEFINED; - } - - auto it = al->begin(); - auto end = al->end(); - int i = 0; - - for (;it != end; it++, i++) { - if (i != idx) { - continue; - } - xmlpp::Attribute *attr = *it; - - return getAttr(ctx, attr); - } - - return JS_UNDEFINED; -} - -static JSValue -js_attributes_item(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) { - return JS_UNDEFINED; - } - - int index; - JS_ToInt32(ctx, &index, argv[0]); - - return js_attributes_item2(ctx, this_val, index); -} - -static JSValue -js_attributes_namedItem2(JSContext *ctx, JSValueConst this_val, const char *str) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element::AttributeList *al = static_cast(js_attributes_GetOpaque(this_val)); - - if (!al) { - return JS_UNDEFINED; - } - - xmlpp::ustring name = str; - - auto it = al->begin(); - auto end = al->end(); - - for (; it != end; ++it) { - auto attr = dynamic_cast(*it); - - if (!attr) { - continue; - } - - if (name == attr->get_name()) { - JSValue obj = getAttr(ctx, attr); - - RETURN_JS(obj); - } - } - - return JS_UNDEFINED; -} - -static JSValue -js_attributes_getNamedItem(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) { - return JS_UNDEFINED; - } - - const char *str; - size_t len; - - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - - JSValue ret = js_attributes_namedItem2(ctx, this_val, str); - JS_FreeCString(ctx, str); - - RETURN_JS(ret); -} - -static JSValue -js_attributes_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, "[attributes object]"); -} - -static const JSCFunctionListEntry js_attributes_proto_funcs[] = { - JS_CGETSET_DEF("length", js_attributes_get_property_length, nullptr), - JS_CFUNC_DEF("item", 1, js_attributes_item), - JS_CFUNC_DEF("getNamedItem", 1, js_attributes_getNamedItem), - JS_CFUNC_DEF("toString", 0, js_attributes_toString) -}; - -#if 0 -static void -js_attributes_finalizer(JSRuntime *rt, JSValue val) -{ - void *node = js_attributes_GetOpaque(val); - - js_attributes_SetOpaque(val, nullptr); - map_attributes.erase(node); -} - -static JSClassDef js_attributes_class = { - "attributes", - js_attributes_finalizer -}; - -#endif - -JSValue -getAttributes(JSContext *ctx, void *node) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - auto node_find = map_attributes.find(node); - - if (node_find != map_attributes.end()) { - JSValue r = JS_DupValue(ctx, node_find->second); - - RETURN_JS(r); - } - JSValue attributes_obj = JS_NewArray(ctx); - JS_SetPropertyFunctionList(ctx, attributes_obj, js_attributes_proto_funcs, countof(js_attributes_proto_funcs)); - - js_attributes_SetOpaque(attributes_obj, node); - js_attributes_set_items(ctx, attributes_obj, node); - map_attributes[node] = attributes_obj; - - JSValue rr = JS_DupValue(ctx, attributes_obj); - - RETURN_JS(rr); -} -#endif diff --git a/src/ecmascript/quickjs/collection.cpp b/src/ecmascript/quickjs/collection.cpp deleted file mode 100644 index 84344c13..00000000 --- a/src/ecmascript/quickjs/collection.cpp +++ /dev/null @@ -1,371 +0,0 @@ -/* The QuickJS html collection object implementation. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "elinks.h" - -#include "bfu/dialog.h" -#include "cache/cache.h" -#include "cookies/cookies.h" -#include "dialogs/menu.h" -#include "dialogs/status.h" -#include "document/html/frames.h" -#include "document/document.h" -#include "document/forms.h" -#include "document/view.h" -#include "ecmascript/ecmascript.h" -#include "ecmascript/quickjs.h" -#include "ecmascript/quickjs/collection.h" -#include "ecmascript/quickjs/element.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/memory.h" -#include "util/string.h" -#include "viewer/text/draw.h" -#include "viewer/text/form.h" -#include "viewer/text/link.h" -#include "viewer/text/vs.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -#ifndef CONFIG_LIBDOM - -static std::map map_collections; -static std::map map_rev_collections; - -static void * -js_htmlCollection_GetOpaque(JSValueConst this_val) -{ - REF_JS(this_val); - - return map_rev_collections[this_val]; -} - -static void -js_htmlCollection_SetOpaque(JSValueConst this_val, void *node) -{ - REF_JS(this_val); - - if (!node) { - map_rev_collections.erase(this_val); - } else { - map_rev_collections[this_val] = node; - } -} - -static JSValue -js_htmlCollection_get_property_length(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Node::NodeSet *ns = static_cast(js_htmlCollection_GetOpaque(this_val)); - - if (!ns) { - return JS_NewInt32(ctx, 0); - } - - return JS_NewInt32(ctx, ns->size()); -} - -static JSValue -js_htmlCollection_item2(JSContext *ctx, JSValueConst this_val, int idx) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Node::NodeSet *ns = static_cast(js_htmlCollection_GetOpaque(this_val)); - - if (!ns) { - return JS_UNDEFINED; - } - - xmlpp::Element *element; - - try { - element = dynamic_cast(ns->at(idx)); - } catch (std::out_of_range &e) { return JS_UNDEFINED;} - - if (!element) { - return JS_UNDEFINED; - } - - return getElement(ctx, element); -} - -static JSValue -js_htmlCollection_item(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) { - return JS_UNDEFINED; - } - - int index; - JS_ToInt32(ctx, &index, argv[0]); - - return js_htmlCollection_item2(ctx, this_val, index); -} - -static JSValue -js_htmlCollection_namedItem2(JSContext *ctx, JSValueConst this_val, const char *str) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Node::NodeSet *ns = static_cast(js_htmlCollection_GetOpaque(this_val)); - - if (!ns) { - return JS_UNDEFINED; - } - - xmlpp::ustring name = str; - - auto it = ns->begin(); - auto end = ns->end(); - - for (; it != end; ++it) { - auto element = dynamic_cast(*it); - - if (!element) { - continue; - } - - if (name == element->get_attribute_value("id") - || name == element->get_attribute_value("name")) { - return getElement(ctx, element); - } - } - - return JS_UNDEFINED; -} - -static JSValue -js_htmlCollection_namedItem(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) { - return JS_UNDEFINED; - } - - const char *str; - size_t len; - - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - - JSValue ret = js_htmlCollection_namedItem2(ctx, this_val, str); - JS_FreeCString(ctx, str); - - RETURN_JS(ret); -} - -static void -js_htmlCollection_set_items(JSContext *ctx, JSValue this_val, void *node) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - int counter = 0; - - xmlpp::Node::NodeSet *ns = static_cast(js_htmlCollection_GetOpaque(this_val)); - - if (!ns) { - return; - } - - xmlpp::Element *element; - - while (1) { - try { - element = dynamic_cast(ns->at(counter)); - } catch (std::out_of_range &e) { return;} - - if (!element) { - return; - } - - JSValue obj = getElement(ctx, element); - - REF_JS(obj); - - JS_SetPropertyUint32(ctx, this_val, counter, JS_DupValue(ctx, obj)); - - xmlpp::ustring name = element->get_attribute_value("id"); - if (name == "") { - name = element->get_attribute_value("name"); - } - if (name != "" && name != "item" && name != "namedItem") { - JS_DefinePropertyValueStr(ctx, this_val, name.c_str(), JS_DupValue(ctx, obj), 0); - } - JS_FreeValue(ctx, obj); - - counter++; - } -} - -static JSValue -js_htmlCollection_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, "[htmlCollection object]"); -} - -static const JSCFunctionListEntry js_htmlCollection_proto_funcs[] = { - JS_CGETSET_DEF("length", js_htmlCollection_get_property_length, nullptr), - JS_CFUNC_DEF("item", 1, js_htmlCollection_item), - JS_CFUNC_DEF("namedItem", 1, js_htmlCollection_namedItem), - JS_CFUNC_DEF("toString", 0, js_htmlCollection_toString) -}; - -#if 0 -static void -js_htmlCollection_finalizer(JSRuntime *rt, JSValue val) -{ - REF_JS(val); - - void *node = js_htmlCollection_GetOpaque(val); - - js_htmlCollection_SetOpaque(val, nullptr); - map_collections.erase(node); -} - -static JSClassDef js_htmlCollection_class = { - "htmlCollection", - js_htmlCollection_finalizer -}; -#endif - -#if 0 -static JSValue -js_htmlCollection_ctor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv) -{ - 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"); - - if (JS_IsException(proto)) { - goto fail; - } - obj = JS_NewObjectProtoClass(ctx, proto, js_htmlCollection_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_htmlCollection_init(JSContext *ctx, JSValue global_obj) -{ - REF_JS(global_obj); - - JSValue htmlCollection_proto, htmlCollection_class; - - /* create the htmlCollection class */ - JS_NewClassID(&js_htmlCollection_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_htmlCollection_class_id, &js_htmlCollection_class); - - htmlCollection_proto = JS_NewObject(ctx); - - REF_JS(htmlCollection_proto); - - JS_SetPropertyFunctionList(ctx, htmlCollection_proto, js_htmlCollection_proto_funcs, countof(js_htmlCollection_proto_funcs)); - - htmlCollection_class = JS_NewCFunction2(ctx, js_htmlCollection_ctor, "htmlCollection", 0, JS_CFUNC_constructor, 0); - - REF_JS(htmlCollection_class); - - /* set proto.constructor and ctor.prototype */ - JS_SetConstructor(ctx, htmlCollection_class, htmlCollection_proto); - JS_SetClassProto(ctx, js_htmlCollection_class_id, htmlCollection_proto); - - JS_SetPropertyStr(ctx, global_obj, "htmlCollection", htmlCollection_proto); - return 0; -} - -#endif - -JSValue -getCollection(JSContext *ctx, void *node) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - auto node_find = map_collections.find(node); - - if (node_find != map_collections.end()) { - JSValue r = JS_DupValue(ctx, node_find->second); - - RETURN_JS(r); - } - JSValue htmlCollection_obj = JS_NewArray(ctx); - JS_SetPropertyFunctionList(ctx, htmlCollection_obj, js_htmlCollection_proto_funcs, countof(js_htmlCollection_proto_funcs)); - - js_htmlCollection_SetOpaque(htmlCollection_obj, node); - js_htmlCollection_set_items(ctx, htmlCollection_obj, node); - map_collections[node] = htmlCollection_obj; - - JSValue rr = JS_DupValue(ctx, htmlCollection_obj); - - RETURN_JS(rr); -} -#endif diff --git a/src/ecmascript/quickjs/console.cpp b/src/ecmascript/quickjs/console.cpp deleted file mode 100644 index 40e43765..00000000 --- a/src/ecmascript/quickjs/console.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* The QuickJS console object implementation. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "elinks.h" - -#include "bfu/dialog.h" -#include "cache/cache.h" -#include "config/home.h" -#include "dialogs/menu.h" -#include "dialogs/status.h" -#include "ecmascript/ecmascript.h" -#include "ecmascript/quickjs.h" -#include "ecmascript/quickjs/console.h" -#include "intl/libintl.h" -#include "osdep/newwin.h" -#include "osdep/sysname.h" -#include "util/conv.h" -#include "util/memory.h" -#include "util/string.h" - -#include -#include "document/renderer.h" -#include "document/refresh.h" -#include "terminal/screen.h" - -#define DEBUG 0 - -#ifndef CONFIG_LIBDOM - -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -static JSClassID js_console_class_id; - -static JSValue -js_console_log_common(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, const char *log_filename) -{ - REF_JS(this_val); - - if (argc != 1 || !log_filename) - { - return JS_UNDEFINED; - } - - if (get_opt_bool("ecmascript.enable_console_log", NULL)) - { - size_t len; - - const char *str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - FILE *f = fopen(log_filename, "a"); - - if (f) - { - fprintf(f, "%s\n", str); - fclose(f); - } - JS_FreeCString(ctx, str); - } - - return JS_UNDEFINED; -} - -static JSValue -js_console_log(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_console_log_common(ctx, this_val, argc, argv, console_log_filename); -} - -static JSValue -js_console_error(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_console_log_common(ctx, this_val, argc, argv, console_error_filename); -} - -static JSValue -js_console_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, "[console object]"); -} - -static const JSCFunctionListEntry js_console_funcs[] = { - JS_CFUNC_DEF("log", 1, js_console_log), - JS_CFUNC_DEF("error", 1, js_console_error), - JS_CFUNC_DEF("toString", 0, js_console_toString) -}; - -static JSClassDef js_console_class = { - "console", -}; - -int -js_console_init(JSContext *ctx) -{ - JSValue console_proto; - - /* create the console class */ - JS_NewClassID(&js_console_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_console_class_id, &js_console_class); - - JSValue global_obj = JS_GetGlobalObject(ctx); - REF_JS(global_obj); - - console_proto = JS_NewObject(ctx); - REF_JS(console_proto); - - JS_SetPropertyFunctionList(ctx, console_proto, js_console_funcs, countof(js_console_funcs)); - JS_SetClassProto(ctx, js_console_class_id, console_proto); - JS_SetPropertyStr(ctx, global_obj, "console", JS_DupValue(ctx, console_proto)); - - JS_FreeValue(ctx, global_obj); - - return 0; -} -#endif diff --git a/src/ecmascript/quickjs/document.cpp b/src/ecmascript/quickjs/document.cpp deleted file mode 100644 index e78bdc93..00000000 --- a/src/ecmascript/quickjs/document.cpp +++ /dev/null @@ -1,1845 +0,0 @@ -/* The QuickJS document object implementation. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "elinks.h" - -#include "ecmascript/ecmascript.h" - -#include "bfu/dialog.h" -#include "cache/cache.h" -#include "cookies/cookies.h" -#include "dialogs/menu.h" -#include "dialogs/status.h" -#include "document/html/frames.h" -#include "document/document.h" -#include "document/forms.h" -#include "document/view.h" -#include "ecmascript/css2xpath.h" -#include "ecmascript/ecmascript.h" -#include "ecmascript/quickjs.h" -#include "ecmascript/quickjs/collection.h" -#include "ecmascript/quickjs/form.h" -#include "ecmascript/quickjs/forms.h" -#include "ecmascript/quickjs/implementation.h" -#include "ecmascript/quickjs/location.h" -#include "ecmascript/quickjs/document.h" -#include "ecmascript/quickjs/element.h" -#include "ecmascript/quickjs/nodelist.h" -#include "ecmascript/quickjs/window.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/memory.h" -#include "util/string.h" -#include "viewer/text/draw.h" -#include "viewer/text/form.h" -#include "viewer/text/link.h" -#include "viewer/text/vs.h" - -#include -#include -#include - -#include -#include -#include - -#ifndef CONFIG_LIBDOM - -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -static xmlpp::Document emptyDoc; -static JSValue getDoctype(JSContext *ctx, void *node); -static JSClassID js_doctype_class_id; -static JSClassID js_document_class_id; - -static JSValue -js_document_get_property_anchors(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 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) { - return JS_NULL; - } - - xmlpp::Document *docu = (xmlpp::Document *)document->dom; - xmlpp::Element* root = (xmlpp::Element *)docu->get_root_node(); - - xmlpp::ustring xpath = "//a"; - xmlpp::Node::NodeSet *elements = new(std::nothrow) xmlpp::Node::NodeSet; - - if (!elements) { - return JS_NULL; - } - - *elements = root->find(xpath); - - if (elements->size() == 0) { - return JS_NULL; - } - - JSValue rr = getCollection(ctx, elements); - JS_FreeValue(ctx, rr); - - RETURN_JS(rr); -} - -static JSValue -js_document_get_property_baseURI(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - - char *str = get_uri_string(vs->uri, URI_BASE); - - if (!str) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - - JSValue ret = JS_NewString(ctx, str); - mem_free(str); - - RETURN_JS(ret); -} - -static JSValue -js_document_get_property_body(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 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) { - return JS_NULL; - } - - xmlpp::Document *docu = (xmlpp::Document *)document->dom; - xmlpp::Element* root = (xmlpp::Element *)docu->get_root_node(); - - xmlpp::ustring xpath = "//body"; - xmlpp::Node::NodeSet elements = root->find(xpath); - - if (elements.size() == 0) { - return JS_NULL; - } - - auto element = elements[0]; - - return getElement(ctx, element); -} - -static JSValue -js_document_set_property_body(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - // TODO - return JS_UNDEFINED; -} - -#ifdef CONFIG_COOKIES -static JSValue -js_document_get_property_cookie(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; - struct string *cookies; - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - cookies = send_cookies_js(vs->uri); - - if (cookies) { - static char cookiestr[1024]; - - strncpy(cookiestr, cookies->source, 1023); - done_string(cookies); - - JSValue r = JS_NewString(ctx, cookiestr); - - RETURN_JS(r); - } else { - JSValue rr = JS_NewStringLen(ctx, "", 0); - - RETURN_JS(rr); - } -} - -static JSValue -js_document_set_property_cookie(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - struct view_state *vs; - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - const char *text; - char *str; - size_t len; - text = JS_ToCStringLen(ctx, &len, val); - - if (!text) { - return JS_EXCEPTION; - } - str = stracpy(text); - if (str) { - set_cookie(vs->uri, str); - mem_free(str); - } - JS_FreeCString(ctx, text); - - return JS_UNDEFINED; -} - -#endif - -static JSValue -js_document_get_property_charset(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 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) { - return JS_NULL; - } - - xmlpp::Document* docu = (xmlpp::Document *)document->dom; - xmlpp::ustring encoding = docu->get_encoding(); - - if (encoding == "") { - encoding = "utf-8"; - } - - JSValue r = JS_NewStringLen(ctx, encoding.c_str(), encoding.length()); - - RETURN_JS(r); -} - -static JSValue -js_document_get_property_childNodes(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; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - struct document *document = vs->doc_view->document; - - if (!document->dom) { - document->dom = document_parse(document); - } - - if (!document->dom) { - return JS_NULL; - } - - xmlpp::Document *docu = (xmlpp::Document *)document->dom; - xmlpp::Element* root = (xmlpp::Element *)docu->get_root_node(); - - if (!root) { - return JS_NULL; - } - - xmlpp::Node::NodeList *nodes = new(std::nothrow) xmlpp::Node::NodeList; - - if (!nodes) { - return JS_NULL; - } - - *nodes = root->get_children(); - if (nodes->empty()) { - delete nodes; - return JS_NULL; - } - - return getNodeList(ctx, nodes); -} - -static JSValue -js_document_get_property_doctype(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 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) { - return JS_NULL; - } - - xmlpp::Document* docu = (xmlpp::Document *)document->dom; - xmlpp::Dtd *dtd = docu->get_internal_subset(); - - if (!dtd) { - return JS_NULL; - } - - return getDoctype(ctx, dtd); -} - -static JSValue -js_document_get_property_documentElement(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 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) { - return JS_NULL; - } - - xmlpp::Document *docu = (xmlpp::Document *)document->dom; - xmlpp::Element* root = (xmlpp::Element *)docu->get_root_node(); - - xmlpp::ustring xpath = "//html"; - xmlpp::Node::NodeSet elements = root->find(xpath); - - if (elements.size() == 0) { - return JS_NULL; - } - - auto element = elements[0]; - - return getElement(ctx, element); -} - -static JSValue -js_document_get_property_documentURI(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { - return JS_NULL; - } - - char *str = get_uri_string(vs->uri, URI_BASE); - - if (!str) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - - JSValue ret = JS_NewString(ctx, str); - mem_free(str); - - RETURN_JS(ret); -} - -static JSValue -js_document_get_property_domain(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - - char *str = get_uri_string(vs->uri, URI_HOST); - - if (!str) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - - JSValue ret = JS_NewString(ctx, str); - mem_free(str); - - RETURN_JS(ret); -} - -static JSValue -js_document_get_property_forms(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 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) { - return JS_NULL; - } - - xmlpp::Document *docu = (xmlpp::Document *)document->dom; - xmlpp::Element* root = (xmlpp::Element *)docu->get_root_node(); - xmlpp::ustring xpath = "//form"; - - xmlpp::Node::NodeSet *elements = new(std::nothrow) xmlpp::Node::NodeSet; - *elements = root->find(xpath); - - if (elements->size() == 0) { - return JS_NULL; - } - JSValue rr = getForms(ctx, elements); - JS_FreeValue(ctx, rr); - - RETURN_JS(rr); -} - -static JSValue -js_document_get_property_head(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 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) { - return JS_NULL; - } - xmlpp::Document *docu = (xmlpp::Document *)document->dom; - xmlpp::Element* root = (xmlpp::Element *)docu->get_root_node(); - - xmlpp::ustring xpath = "//head"; - xmlpp::Node::NodeSet elements = root->find(xpath); - - if (elements.size() == 0) { - return JS_NULL; - } - - auto element = elements[0]; - - return getElement(ctx, element); -} - -static JSValue -js_document_get_property_images(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 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) { - return JS_NULL; - } - xmlpp::Document *docu = (xmlpp::Document *)document->dom; - xmlpp::Element* root = (xmlpp::Element *)docu->get_root_node(); - - xmlpp::ustring xpath = "//img"; - xmlpp::Node::NodeSet *elements = new(std::nothrow) xmlpp::Node::NodeSet; - - if (!elements) { - return JS_NULL; - } - - *elements = root->find(xpath); - - if (elements->size() == 0) { - return JS_NULL; - } - - JSValue rr = getCollection(ctx, elements); - JS_FreeValue(ctx, rr); - - RETURN_JS(rr); -} - -static JSValue -js_document_get_property_implementation(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 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) { - return JS_NULL; - } - - return getImplementation(ctx); -} - -static JSValue -js_document_get_property_links(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 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) { - return JS_NULL; - } - xmlpp::Document *docu = (xmlpp::Document *)document->dom; - xmlpp::Element* root = (xmlpp::Element *)docu->get_root_node(); - - xmlpp::ustring xpath = "//a[@href]|//area[@href]"; - xmlpp::Node::NodeSet *elements = new(std::nothrow) xmlpp::Node::NodeSet; - - if (!elements) { - return JS_NULL; - } - - *elements = root->find(xpath); - - if (elements->size() == 0) { - return JS_NULL; - } - JSValue rr = getCollection(ctx, elements); - JS_FreeValue(ctx, rr); - - RETURN_JS(rr); -} - -static JSValue -js_document_get_property_location(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); - - JSValue ret = JS_DupValue(ctx, interpreter->location_obj); - - RETURN_JS(ret); -} - -static JSValue -js_document_get_property_nodeType(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - return JS_NewInt32(ctx, 9); -} - -static JSValue -js_document_set_property_location(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - struct view_state *vs; - struct document_view *doc_view; - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - const char *url; - size_t len; - - url = JS_ToCStringLen(ctx, &len, val); - - if (!url) { - return JS_EXCEPTION; - } - - location_goto_const(doc_view, url); - JS_FreeCString(ctx, url); - - return JS_UNDEFINED; -} - -static JSValue -js_document_get_property_referrer(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; - struct document_view *doc_view; - struct document *document; - struct session *ses; - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - ses = doc_view->session; - - switch (get_opt_int("protocol.http.referer.policy", NULL)) { - case REFERER_NONE: - /* oh well */ - return JS_UNDEFINED; - - case REFERER_FAKE: - return JS_NewString(ctx, get_opt_str("protocol.http.referer.fake", NULL)); - - case REFERER_TRUE: - /* XXX: Encode as in add_url_to_httset_prop_string(&prop, ) ? --pasky */ - if (ses->referrer) { - char *str = get_uri_string(ses->referrer, URI_HTTP_REFERRER); - - if (str) { - JSValue ret = JS_NewString(ctx, str); - mem_free(str); - - RETURN_JS(ret); - } else { - return JS_UNDEFINED; - } - } - break; - - case REFERER_SAME_URL: - char *str = get_uri_string(document->uri, URI_HTTP_REFERRER); - - if (str) { - JSValue ret = JS_NewString(ctx, str); - mem_free(str); - - RETURN_JS(ret); - } else { - return JS_UNDEFINED; - } - break; - } - - return JS_UNDEFINED; -} - -static JSValue -js_document_get_property_scripts(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 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) { - return JS_NULL; - } - - xmlpp::Document *docu = (xmlpp::Document *)document->dom; - xmlpp::Element* root = (xmlpp::Element *)docu->get_root_node(); - - xmlpp::ustring xpath = "//script"; - xmlpp::Node::NodeSet *elements = new(std::nothrow) xmlpp::Node::NodeSet; - - if (!elements) { - return JS_NULL; - } - - *elements = root->find(xpath); - - if (elements->size() == 0) { - return JS_NULL; - } - JSValue rr = getCollection(ctx, elements); - JS_FreeValue(ctx, rr); - - RETURN_JS(rr); -} - -static JSValue -js_document_get_property_title(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; - struct document_view *doc_view; - struct document *document; - - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - JSValue r = JS_NewString(ctx, document->title); - RETURN_JS(r); -} - -static JSValue -js_document_set_property_title(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - vs = interpreter->vs; - - if (!vs || !vs->doc_view) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - - const char *str; - char *string; - size_t len; - - str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - - string = stracpy(str); - JS_FreeCString(ctx, str); - - mem_free_set(&document->title, string); - print_screen_status(doc_view->session); - - return JS_UNDEFINED; -} - -static JSValue -js_document_get_property_url(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; - struct document_view *doc_view; - struct document *document; - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - char *str = get_uri_string(document->uri, URI_ORIGINAL); - - if (str) { - JSValue ret = JS_NewString(ctx, str); - mem_free(str); - - RETURN_JS(ret); - } else { - return JS_UNDEFINED; - } -} - -static JSValue -js_document_set_property_url(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - struct view_state *vs; - struct document_view *doc_view; - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - const char *url; - size_t len; - - url = JS_ToCStringLen(ctx, &len, val); - - if (!url) { - return JS_EXCEPTION; - } - location_goto_const(doc_view, url); - JS_FreeCString(ctx, url); - - return JS_UNDEFINED; -} - - -static JSValue -js_document_write_do(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int newline) -{ -#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); - - if (argc >= 1) { - int element_offset = interpreter->element_offset; - struct string string; - - if (init_string(&string)) { - for (int i = 0; i < argc; ++i) { - const char *str; - size_t len; - - str = JS_ToCStringLen(ctx, &len, argv[i]); - - if (!str) { - done_string(&string); - return JS_EXCEPTION; - } - add_bytes_to_string(&string, str, len); - JS_FreeCString(ctx, str); - } - - if (newline) { - add_to_string(&string, "\n"); - } - - if (element_offset == interpreter->current_writecode->element_offset) { - add_string_to_string(&interpreter->current_writecode->string, &string); - done_string(&string); - } else { - (void)add_to_ecmascript_string_list(&interpreter->writecode, string.source, string.length, element_offset); - done_string(&string); - interpreter->current_writecode = interpreter->current_writecode->next; - } - interpreter->changed = true; - } - } - -#ifdef CONFIG_LEDS - set_led_value(interpreter->vs->doc_view->session->status.ecmascript_led, 'J'); -#endif - return JS_FALSE; -} - -/* @document_funcs{"write"} */ -static JSValue -js_document_write(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_document_write_do(ctx, this_val, argc, argv, 0); -} - -/* @document_funcs{"writeln"} */ -static JSValue -js_document_writeln(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_document_write_do(ctx, this_val, argc, argv, 1); -} - -/* @document_funcs{"replace"} */ -static JSValue -js_document_replace(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#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 document_view *doc_view = interpreter->vs->doc_view; - struct document *document; - document = doc_view->document; - - if (argc != 2) { - return JS_FALSE; - } - - struct string needle; - struct string heystack; - - if (!init_string(&needle)) { - return JS_EXCEPTION; - } - if (!init_string(&heystack)) { - done_string(&needle); - return JS_EXCEPTION; - } - - const char *str; - size_t len; - - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (str) { - add_bytes_to_string(&needle, str, len); - JS_FreeCString(ctx, str); - } - - str = JS_ToCStringLen(ctx, &len, argv[1]); - - if (str) { - add_bytes_to_string(&heystack, str, len); - JS_FreeCString(ctx, str); - } - //DBG("doc replace %s %s\n", needle.source, heystack.source); - - struct cache_entry *cached = doc_view->document->cached; - struct fragment *f = get_cache_fragment(cached); - - if (f && f->length) - { - struct string f_data; - if (init_string(&f_data)) { - add_bytes_to_string(&f_data, f->data, f->length); - - struct string nu_str; - if (init_string(&nu_str)) { - string_replace(&nu_str, &f_data, &needle, &heystack); - delete_entry_content(cached); - /* TBD: somehow better rerender the document - * now it's places on the session level in doc_loading_callback */ - add_fragment(cached, 0, nu_str.source, nu_str.length); - normalize_cache_entry(cached, nu_str.length); - document->ecmascript_counter++; - done_string(&nu_str); - } - //DBG("doc replace %s %s\n", needle.source, heystack.source); - done_string(&f_data); - } - } - - done_string(&needle); - done_string(&heystack); - - return JS_TRUE; -} - -static JSValue -js_document_createComment(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) { - return JS_FALSE; - } - xmlpp::Element* emptyRoot = (xmlpp::Element *)emptyDoc.get_root_node(); - - if (!emptyRoot) { - emptyDoc.create_root_node("root"); - } - - emptyRoot = (xmlpp::Element *)emptyDoc.get_root_node(); - - if (!emptyRoot) { - return JS_NULL; - } - const char *str; - size_t len; - - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - xmlpp::ustring text = str; - JS_FreeCString(ctx, str); - xmlpp::CommentNode *comment = emptyRoot->add_child_comment(text); - - if (!comment) { - return JS_NULL; - } - - return getElement(ctx, comment); -} - -static JSValue -js_document_createDocumentFragment(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 != 0) { - return JS_FALSE; - } - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - 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) { - return JS_NULL; - } - - xmlpp::Document *doc2 = static_cast(document->dom); - xmlDoc *docu = doc2->cobj(); - xmlNode *xmlnode = xmlNewDocFragment(docu); - - if (!xmlnode) { - return JS_NULL; - } - - xmlpp::Node *node = new(std::nothrow) xmlpp::Node(xmlnode); - - if (!node) { - return JS_NULL; - } - - return getElement(ctx, node); -} - -static JSValue -js_document_createElement(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) { - return JS_FALSE; - } - xmlpp::Element* emptyRoot = (xmlpp::Element *)emptyDoc.get_root_node(); - - if (!emptyRoot) { - emptyDoc.create_root_node("root"); - } - - emptyRoot = (xmlpp::Element *)emptyDoc.get_root_node(); - - if (!emptyRoot) { - return JS_NULL; - } - const char *str; - size_t len; - - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - xmlpp::ustring text = str; - JS_FreeCString(ctx, str); - xmlpp::Element *elem = emptyRoot->add_child_element(text); - - if (!elem) { - return JS_NULL; - } - - return getElement(ctx, elem); -} - -static JSValue -js_document_createTextNode(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) { - return JS_FALSE; - } - xmlpp::Element* emptyRoot = (xmlpp::Element *)emptyDoc.get_root_node(); - - if (!emptyRoot) { - emptyDoc.create_root_node("root"); - } - - emptyRoot = (xmlpp::Element *)emptyDoc.get_root_node(); - - if (!emptyRoot) { - return JS_NULL; - } - const char *str; - size_t len; - - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - xmlpp::ustring text = str; - JS_FreeCString(ctx, str); - xmlpp::TextNode *textNode = emptyRoot->add_child_text(text); - - if (!textNode) { - return JS_NULL; - } - - return getElement(ctx, textNode); -} - -static JSValue -js_document_getElementById(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) { - return JS_FALSE; - } - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - 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) { - return JS_NULL; - } - - xmlpp::Document *docu = (xmlpp::Document *)document->dom; - xmlpp::Element* root = (xmlpp::Element *)docu->get_root_node(); - const char *str; - size_t len; - - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - xmlpp::ustring id = str; - JS_FreeCString(ctx, str); - xmlpp::ustring xpath = "//*[@id=\""; - xpath += id; - xpath += "\"]"; - - auto elements = root->find(xpath); - - if (elements.size() == 0) { - return JS_NULL; - } - - auto node = elements[0]; - - return getElement(ctx, node); -} - -static JSValue -js_document_getElementsByClassName(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) { - return JS_FALSE; - } - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - 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) { - return JS_NULL; - } - - xmlpp::Document *docu = (xmlpp::Document *)document->dom; - xmlpp::Element* root = (xmlpp::Element *)docu->get_root_node(); - - const char *str; - size_t len; - - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - xmlpp::ustring id = str; - JS_FreeCString(ctx, str); - - xmlpp::ustring xpath = "//*[@class=\""; - xpath += id; - xpath += "\"]"; - xmlpp::Node::NodeSet *elements = new(std::nothrow) xmlpp::Node::NodeSet; - - if (!elements) { - return JS_NULL; - } - *elements = root->find(xpath); - JSValue rr = getCollection(ctx, elements); - JS_FreeValue(ctx, rr); - - RETURN_JS(rr); -} - -static JSValue -js_document_getElementsByName(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) { - return JS_FALSE; - } - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - 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) { - return JS_NULL; - } - - xmlpp::Document *docu = (xmlpp::Document *)document->dom; - xmlpp::Element* root = (xmlpp::Element *)docu->get_root_node(); - - const char *str; - size_t len; - - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - xmlpp::ustring id = str; - JS_FreeCString(ctx, str); - xmlpp::ustring xpath = "//*[@id=\""; - xpath += id; - xpath += "\"]|//*[@name=\""; - xpath += id; - xpath += "\"]"; - xmlpp::Node::NodeSet *elements = new(std::nothrow) xmlpp::Node::NodeSet; - - if (!elements) { - return JS_NULL; - } - *elements = root->find(xpath); - JSValue rr = getCollection(ctx, elements); - JS_FreeValue(ctx, rr); - - RETURN_JS(rr); -} - -static JSValue -js_document_getElementsByTagName(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) { - return JS_FALSE; - } - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - 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) { - return JS_NULL; - } - xmlpp::Document *docu = (xmlpp::Document *)document->dom; - xmlpp::Element* root = (xmlpp::Element *)docu->get_root_node(); - const char *str; - size_t len; - - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - xmlpp::ustring id = str; - JS_FreeCString(ctx, str); - std::transform(id.begin(), id.end(), id.begin(), ::tolower); - - xmlpp::ustring xpath = "//"; - xpath += id; - xmlpp::Node::NodeSet *elements = new(std::nothrow) xmlpp::Node::NodeSet; - - if (!elements) { - return JS_NULL; - } - *elements = root->find(xpath); - JSValue rr = getCollection(ctx, elements); - JS_FreeValue(ctx, rr); - - RETURN_JS(rr); -} - -static JSValue -js_document_querySelector(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) { - return JS_FALSE; - } - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - 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) { - return JS_NULL; - } - - xmlpp::Document *docu = (xmlpp::Document *)document->dom; - xmlpp::Element* root = (xmlpp::Element *)docu->get_root_node(); - const char *str; - size_t len; - - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - xmlpp::ustring css = str; - JS_FreeCString(ctx, str); - xmlpp::ustring xpath = css2xpath(css); - - xmlpp::Node::NodeSet elements; - - try { - elements = root->find(xpath); - } catch (xmlpp::exception &e) { - return JS_NULL; - } - - if (elements.size() == 0) { - return JS_NULL; - } - - auto node = elements[0]; - - return getElement(ctx, node); -} - -static JSValue -js_document_querySelectorAll(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) { - return JS_FALSE; - } - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - 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) { - return JS_NULL; - } - - xmlpp::Document *docu = (xmlpp::Document *)document->dom; - xmlpp::Element* root = (xmlpp::Element *)docu->get_root_node(); - const char *str; - size_t len; - - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - xmlpp::ustring css = str; - JS_FreeCString(ctx, str); - xmlpp::ustring xpath = css2xpath(css); - xmlpp::Node::NodeSet *elements = new(std::nothrow) xmlpp::Node::NodeSet; - - if (!elements) { - return JS_NULL; - } - - try { - *elements = root->find(xpath); - } catch (xmlpp::exception &e) { - } - JSValue rr = getCollection(ctx, elements); - JS_FreeValue(ctx, rr); - - RETURN_JS(rr); -} - -#if 0 -JSClass doctype_class = { - "doctype", - JSCLASS_HAS_PRIVATE, - &doctype_ops -}; -#endif - -static JSValue -js_doctype_get_property_name(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Dtd *dtd = static_cast(JS_GetOpaque(this_val, js_doctype_class_id)); - - if (!dtd) { - return JS_NULL; - } - xmlpp::ustring v = dtd->get_name(); - - return JS_NewStringLen(ctx, v.c_str(), v.length()); -} - -static JSValue -js_doctype_get_property_publicId(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Dtd *dtd = static_cast(JS_GetOpaque(this_val, js_doctype_class_id)); - - if (!dtd) { - return JS_NULL; - } - xmlpp::ustring v = dtd->get_external_id(); - - JSValue r = JS_NewStringLen(ctx, v.c_str(), v.length()); - RETURN_JS(r); -} - -static JSValue -js_doctype_get_property_systemId(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Dtd *dtd = static_cast(JS_GetOpaque(this_val, js_doctype_class_id)); - - if (!dtd) { - return JS_NULL; - } - xmlpp::ustring v = dtd->get_system_id(); - - JSValue r = JS_NewStringLen(ctx, v.c_str(), v.length()); - RETURN_JS(r); -} - -static JSValue -js_document_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, "[document object]"); -} - -static const JSCFunctionListEntry js_document_proto_funcs[] = { - JS_CGETSET_DEF("anchors", js_document_get_property_anchors, nullptr), - JS_CGETSET_DEF("baseURI", js_document_get_property_baseURI, nullptr), - JS_CGETSET_DEF("body", js_document_get_property_body, js_document_set_property_body), -#ifdef CONFIG_COOKIES - JS_CGETSET_DEF("cookie", js_document_get_property_cookie, js_document_set_property_cookie), -#endif - JS_CGETSET_DEF("charset", js_document_get_property_charset, nullptr), - JS_CGETSET_DEF("characterSet", js_document_get_property_charset, nullptr), - JS_CGETSET_DEF("childNodes", js_document_get_property_childNodes, nullptr), - JS_CGETSET_DEF("doctype", js_document_get_property_doctype, nullptr), - JS_CGETSET_DEF("documentElement", js_document_get_property_documentElement, nullptr), - JS_CGETSET_DEF("documentURI", js_document_get_property_documentURI, nullptr), - JS_CGETSET_DEF("domain", js_document_get_property_domain, nullptr), - JS_CGETSET_DEF("forms", js_document_get_property_forms, nullptr), - JS_CGETSET_DEF("head", js_document_get_property_head, nullptr), - JS_CGETSET_DEF("images", js_document_get_property_images, nullptr), - JS_CGETSET_DEF("implementation", js_document_get_property_implementation, nullptr), - JS_CGETSET_DEF("inputEncoding", js_document_get_property_charset, nullptr), - JS_CGETSET_DEF("links", js_document_get_property_links, nullptr), - JS_CGETSET_DEF("location", js_document_get_property_location, js_document_set_property_location), - JS_CGETSET_DEF("nodeType", js_document_get_property_nodeType, nullptr), - JS_CGETSET_DEF("referrer", js_document_get_property_referrer, nullptr), - JS_CGETSET_DEF("scripts", js_document_get_property_scripts, nullptr), - JS_CGETSET_DEF("title", js_document_get_property_title, js_document_set_property_title), /* TODO: Charset? */ - JS_CGETSET_DEF("URL", js_document_get_property_url, js_document_set_property_url), - - JS_CFUNC_DEF("createComment", 1, js_document_createComment), - JS_CFUNC_DEF("createDocumentFragment", 0, js_document_createDocumentFragment), - JS_CFUNC_DEF("createElement", 1, js_document_createElement), - JS_CFUNC_DEF("createTextNode", 1, js_document_createTextNode), - JS_CFUNC_DEF("write", 1, js_document_write), - JS_CFUNC_DEF("writeln", 1, js_document_writeln), - JS_CFUNC_DEF("replace", 2, js_document_replace), - JS_CFUNC_DEF("getElementById", 1, js_document_getElementById), - JS_CFUNC_DEF("getElementsByClassName", 1, js_document_getElementsByClassName), - JS_CFUNC_DEF("getElementsByName", 1, js_document_getElementsByName), - JS_CFUNC_DEF("getElementsByTagName", 1, js_document_getElementsByTagName), - JS_CFUNC_DEF("querySelector", 1, js_document_querySelector), - JS_CFUNC_DEF("querySelectorAll", 1, js_document_querySelectorAll), - - JS_CFUNC_DEF("toString", 0, js_document_toString) -}; - -static JSClassDef js_document_class = { - "document", -}; - -JSValue -js_document_init(JSContext *ctx) -{ - JSValue document_proto; - - /* create the document class */ - JS_NewClassID(&js_document_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_document_class_id, &js_document_class); - - JSValue global_obj = JS_GetGlobalObject(ctx); - REF_JS(global_obj); - - document_proto = JS_NewObject(ctx); - REF_JS(document_proto); - - JS_SetPropertyFunctionList(ctx, document_proto, js_document_proto_funcs, countof(js_document_proto_funcs)); - JS_SetClassProto(ctx, js_document_class_id, document_proto); - JS_SetPropertyStr(ctx, global_obj, "document", JS_DupValue(ctx, document_proto)); - - JS_FreeValue(ctx, global_obj); - - RETURN_JS(document_proto); -} - -static JSValue -js_doctype_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, "[doctype object]"); -} - -static const JSCFunctionListEntry js_doctype_proto_funcs[] = { - JS_CGETSET_DEF("name", js_doctype_get_property_name, nullptr), - JS_CGETSET_DEF("publicId", js_doctype_get_property_publicId, nullptr), - JS_CGETSET_DEF("systemId", js_doctype_get_property_systemId, nullptr), - JS_CFUNC_DEF("toString", 0, js_doctype_toString) -}; - -static std::map map_doctypes; - -static void -js_doctype_finalizer(JSRuntime *rt, JSValue val) -{ - REF_JS(val); - - void *node = JS_GetOpaque(val, js_doctype_class_id); - map_doctypes.erase(node); -} - -static JSClassDef js_doctype_class = { - "doctype", - js_doctype_finalizer -}; - -int -js_doctype_init(JSContext *ctx) -{ - JSValue doctype_proto; - - /* create the doctype class */ - JS_NewClassID(&js_doctype_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_doctype_class_id, &js_doctype_class); - - JSValue global_obj = JS_GetGlobalObject(ctx); - REF_JS(global_obj); - - doctype_proto = JS_NewObject(ctx); - REF_JS(doctype_proto); - - JS_SetPropertyFunctionList(ctx, doctype_proto, js_doctype_proto_funcs, countof(js_doctype_proto_funcs)); - JS_SetClassProto(ctx, js_doctype_class_id, doctype_proto); - JS_SetPropertyStr(ctx, global_obj, "doctype", JS_DupValue(ctx, doctype_proto)); - - JS_FreeValue(ctx, global_obj); - - return 0; -} - -static JSValue -getDoctype(JSContext *ctx, void *node) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - static int initialized; - /* create the element class */ - if (!initialized) { - JS_NewClassID(&js_doctype_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_doctype_class_id, &js_doctype_class); - initialized = 1; - map_doctypes.clear(); - } - auto node_find = map_doctypes.find(node); - - if (node_find != map_doctypes.end()) { - JSValue r = JS_DupValue(ctx, node_find->second); - RETURN_JS(r); - } - JSValue doctype_obj = JS_NewObjectClass(ctx, js_doctype_class_id); - JS_SetPropertyFunctionList(ctx, doctype_obj, js_doctype_proto_funcs, countof(js_doctype_proto_funcs)); - JS_SetClassProto(ctx, js_doctype_class_id, doctype_obj); - JS_SetOpaque(doctype_obj, node); - - map_doctypes[node] = doctype_obj; - - JSValue rr = JS_DupValue(ctx, doctype_obj); - RETURN_JS(rr); -} - -JSValue -getDocument(JSContext *ctx, void *doc) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - JSValue document_obj = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, document_obj, js_document_proto_funcs, countof(js_document_proto_funcs)); -// document_class = JS_NewCFunction2(ctx, js_document_ctor, "document", 0, JS_CFUNC_constructor, 0); -// JS_SetConstructor(ctx, document_class, document_obj); - JS_SetClassProto(ctx, js_document_class_id, document_obj); - JS_SetOpaque(document_obj, doc); - - RETURN_JS(document_obj); -} -#endif diff --git a/src/ecmascript/quickjs/element.cpp b/src/ecmascript/quickjs/element.cpp deleted file mode 100644 index e69bdd35..00000000 --- a/src/ecmascript/quickjs/element.cpp +++ /dev/null @@ -1,2238 +0,0 @@ -/* The QuickJS html element objects implementation. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "elinks.h" - -#include "bfu/dialog.h" -#include "cache/cache.h" -#include "cookies/cookies.h" -#include "dialogs/menu.h" -#include "dialogs/status.h" -#include "document/html/frames.h" -#include "document/document.h" -#include "document/forms.h" -#include "document/view.h" -#include "ecmascript/css2xpath.h" -#include "ecmascript/ecmascript.h" -#include "ecmascript/quickjs.h" -#include "ecmascript/quickjs/attr.h" -#include "ecmascript/quickjs/attributes.h" -#include "ecmascript/quickjs/collection.h" -#include "ecmascript/quickjs/element.h" -#include "ecmascript/quickjs/heartbeat.h" -#include "ecmascript/quickjs/keyboard.h" -#include "ecmascript/quickjs/nodelist.h" -#include "ecmascript/quickjs/window.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/memory.h" -#include "util/string.h" -#include "viewer/text/draw.h" -#include "viewer/text/form.h" -#include "viewer/text/link.h" -#include "viewer/text/vs.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#ifndef CONFIG_LIBDOM - -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -static JSClassID js_element_class_id; - -struct listener { - LIST_HEAD(struct listener); - char *typ; - JSValue fun; -}; - -struct js_element_private { - LIST_OF(struct listener) listeners; - struct ecmascript_interpreter *interpreter; - JSValue thisval; - void *node; -}; - -static void * -js_getopaque(JSValueConst obj, JSClassID class_id) -{ - REF_JS(obj); - - struct js_element_private *res = (struct js_element_private *)JS_GetOpaque(obj, class_id); - - if (!res) { - return NULL; - } - return res->node; -} - -static JSValue -js_element_get_property_attributes(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - - xmlpp::Element::AttributeList *attrs = new(std::nothrow) xmlpp::Element::AttributeList; - - if (!attrs) { - return JS_NULL; - } - *attrs = el->get_attributes(); - JSValue rr = getAttributes(ctx, attrs); - JS_FreeValue(ctx, rr); - - RETURN_JS(rr); -} - -static JSValue -js_element_get_property_children(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - - auto nodes = el->get_children(); - if (nodes.empty()) { - return JS_NULL; - } - - xmlpp::Node::NodeSet *list = new(std::nothrow) xmlpp::Node::NodeSet; - - if (!list) { - return JS_NULL; - } - - auto it = nodes.begin(); - auto end = nodes.end(); - - for (; it != end; ++it) { - const auto element = dynamic_cast(*it); - - if (element) { - list->push_back(reinterpret_cast(element)); - } - } - - if (list->empty()) { - delete list; - return JS_NULL; - } - JSValue rr = getCollection(ctx, list); - JS_FreeValue(ctx, rr); - - RETURN_JS(rr); -} - -static JSValue -js_element_get_property_childElementCount(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - - int res = el->get_children().size(); - - return JS_NewUint32(ctx, res); -} - -static JSValue -js_element_get_property_childNodes(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - - xmlpp::Node::NodeList *nodes = new(std::nothrow) xmlpp::Node::NodeList; - - if (!nodes) { - return JS_NULL; - } - - *nodes = el->get_children(); - if (nodes->empty()) { - delete nodes; - return JS_NULL; - } - JSValue rr = getNodeList(ctx, nodes); - JS_FreeValue(ctx, rr); - - RETURN_JS(rr); -} - -static JSValue -js_element_get_property_className(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - xmlpp::ustring v = el->get_attribute_value("class"); - - JSValue r = JS_NewStringLen(ctx, v.c_str(), v.length()); - RETURN_JS(r); -} - -static JSValue -js_element_get_property_dir(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - - xmlpp::ustring v = el->get_attribute_value("dir"); - - if (v != "auto" && v != "ltr" && v != "rtl") { - v = ""; - } - JSValue r = JS_NewStringLen(ctx, v.c_str(), v.length()); - RETURN_JS(r); -} - -static JSValue -js_element_get_property_firstChild(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - - auto node = el->get_first_child(); - - if (!node) { - return JS_NULL; - } - - return getElement(ctx, node); -} - -static JSValue -js_element_get_property_firstElementChild(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - - auto nodes = el->get_children(); - if (nodes.empty()) { - return JS_NULL; - } - - auto it = nodes.begin(); - auto end = nodes.end(); - - for (; it != end; ++it) { - auto element = dynamic_cast(*it); - - if (element) { - return getElement(ctx, element); - } - } - return JS_NULL; -} - -static JSValue -js_element_get_property_id(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - xmlpp::ustring v = el->get_attribute_value("id"); - - JSValue r = JS_NewStringLen(ctx, v.c_str(), v.length()); - RETURN_JS(r); -} - -static JSValue -js_element_get_property_lang(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - xmlpp::ustring v = el->get_attribute_value("lang"); - - JSValue r = JS_NewStringLen(ctx, v.c_str(), v.length()); - RETURN_JS(r); -} - -static JSValue -js_element_get_property_lastChild(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - auto nodes = el->get_children(); - - if (nodes.empty()) { - return JS_NULL; - } - - return getElement(ctx, *(nodes.rbegin())); -} - -static JSValue -js_element_get_property_lastElementChild(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - auto nodes = el->get_children(); - - if (nodes.empty()) { - return JS_NULL; - } - - auto it = nodes.rbegin(); - auto end = nodes.rend(); - - for (; it != end; ++it) { - auto element = dynamic_cast(*it); - - if (element) { - return getElement(ctx, element); - } - } - - return JS_NULL; -} - -static JSValue -js_element_get_property_nextElementSibling(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - xmlpp::Node *node = el; - - while (true) { - node = node->get_next_sibling(); - - if (!node) { - return JS_NULL; - } - xmlpp::Element *next = dynamic_cast(node); - - if (next) { - return getElement(ctx, next); - } - } - - return JS_NULL; -} - -static JSValue -js_element_get_property_nodeName(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Node *node = static_cast(js_getopaque(this_val, js_element_class_id)); - - xmlpp::ustring v; - - if (!node) { - JSValue r = JS_NewStringLen(ctx, "", 0); - RETURN_JS(r); - } - auto el = dynamic_cast(node); - - if (el) { - v = el->get_name(); - std::transform(v.begin(), v.end(), v.begin(), ::toupper); - } else { - auto el = dynamic_cast(node); - if (el) { - v = el->get_name(); - } else if (dynamic_cast(node)) { - v = "#text"; - } else if (dynamic_cast(node)) { - v = "#comment"; - } - } - - JSValue rr = JS_NewStringLen(ctx, v.c_str(), v.length()); - RETURN_JS(rr); -} - -static JSValue -js_element_get_property_nodeType(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Node *node = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!node) { - return JS_NULL; - } - - int ret = 8; - - if (dynamic_cast(node)) { - ret = 1; - } else if (dynamic_cast(node)) { - ret = 2; - } else if (dynamic_cast(node)) { - ret = 3; - } else if (dynamic_cast(node)) { - ret = 8; - } - return JS_NewUint32(ctx, ret); -} - -static JSValue -js_element_get_property_nodeValue(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Node *node = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!node) { - return JS_NULL; - } - - if (dynamic_cast(node)) { - return JS_NULL; - } - - auto el = dynamic_cast(node); - - if (el) { - xmlpp::ustring v = el->get_value(); - - JSValue r = JS_NewStringLen(ctx, v.c_str(), v.length()); - RETURN_JS(r); - } - - auto el2 = dynamic_cast(node); - - if (el2) { - xmlpp::ustring v = el2->get_content(); - - JSValue r = JS_NewStringLen(ctx, v.c_str(), v.length()); - RETURN_JS(r); - } - - auto el3 = dynamic_cast(node); - - if (el3) { - xmlpp::ustring v = el3->get_content(); - - JSValue r = JS_NewStringLen(ctx, v.c_str(), v.length()); - RETURN_JS(r); - } - - return JS_UNDEFINED; -} - -static JSValue -js_element_get_property_nextSibling(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - - auto node = el->get_next_sibling(); - - if (!node) { - return JS_NULL; - } - - return getElement(ctx, node); -} - -static JSValue -js_element_get_property_ownerDocument(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); - - JSValue r = JS_DupValue(ctx, interpreter->document_obj); - RETURN_JS(r); -} - -static JSValue -js_element_get_property_parentElement(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - - auto node = dynamic_cast(el->get_parent()); - - if (!node) { - return JS_NULL; - } - - return getElement(ctx, node); -} - -static JSValue -js_element_get_property_parentNode(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - auto node = el->get_parent(); - - if (!node) { - return JS_NULL; - } - - return getElement(ctx, node); -} - -static JSValue -js_element_get_property_previousElementSibling(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - xmlpp::Node *node = el; - - while (true) { - node = node->get_previous_sibling(); - - if (!node) { - return JS_NULL; - } - xmlpp::Element *next = dynamic_cast(node); - - if (next) { - return getElement(ctx, next); - } - } - - return JS_NULL; -} - -static JSValue -js_element_get_property_previousSibling(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - auto node = el->get_previous_sibling(); - - if (!node) { - return JS_NULL; - } - - return getElement(ctx, node); -} - -static JSValue -js_element_get_property_tagName(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - xmlpp::ustring v = el->get_name(); - std::transform(v.begin(), v.end(), v.begin(), ::toupper); - - JSValue r = JS_NewStringLen(ctx, v.c_str(), v.length()); - RETURN_JS(r); -} - -static JSValue -js_element_get_property_title(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - xmlpp::ustring v = el->get_attribute_value("title"); - - JSValue r = JS_NewStringLen(ctx, v.c_str(), v.length()); - RETURN_JS(r); -} - -static void -dump_element(struct string *buf, xmlpp::Element *element, bool toSort = false) -{ - add_char_to_string(buf, '<'); - add_to_string(buf, element->get_name().c_str()); - auto attrs = element->get_attributes(); - if (toSort) { - attrs.sort([](const xmlpp::Attribute *a1, const xmlpp::Attribute *a2) - { - if (a1->get_name() == a2->get_name()) { - return a1->get_value() < a2->get_value(); - } - return a1->get_name() < a2->get_name(); - }); - } - auto it = attrs.begin(); - auto end = attrs.end(); - for (;it != end; ++it) { - add_char_to_string(buf, ' '); - add_to_string(buf, (*it)->get_name().c_str()); - add_char_to_string(buf, '='); - add_char_to_string(buf, '"'); - add_to_string(buf, (*it)->get_value().c_str()); - add_char_to_string(buf, '"'); - } - add_char_to_string(buf, '>'); -} - -void -walk_tree(struct string *buf, void *nod, bool start, bool toSortAttrs) -{ - xmlpp::Node *node = static_cast(nod); - - if (!start) { - const auto textNode = dynamic_cast(node); - - if (textNode) { - add_bytes_to_string(buf, textNode->get_content().c_str(), textNode->get_content().length()); - } else { - auto element = dynamic_cast(node); - - if (element) { - dump_element(buf, element, toSortAttrs); - } - } - } - - auto childs = node->get_children(); - auto it = childs.begin(); - auto end = childs.end(); - - for (; it != end; ++it) { - walk_tree(buf, *it, false, toSortAttrs); - } - - if (!start) { - const auto element = dynamic_cast(node); - if (element) { - add_to_string(buf, "get_name().c_str()); - add_char_to_string(buf, '>'); - } - } -} - -static void -walk_tree_content(struct string *buf, xmlpp::Node *node) -{ - const auto nodeText = dynamic_cast(node); - - if (nodeText) { - add_bytes_to_string(buf, nodeText->get_content().c_str(), nodeText->get_content().length()); - } - - auto childs = node->get_children(); - auto it = childs.begin(); - auto end = childs.end(); - - for (; it != end; ++it) { - walk_tree_content(buf, *it); - } -} - -static JSValue -js_element_get_property_innerHtml(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - struct string buf; - if (!init_string(&buf)) { - return JS_EXCEPTION; - } - walk_tree(&buf, el, true, false); - JSValue ret = JS_NewStringLen(ctx, buf.source, buf.length); - done_string(&buf); - - RETURN_JS(ret); -} - -static JSValue -js_element_get_property_outerHtml(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - struct string buf; - if (!init_string(&buf)) { - return JS_EXCEPTION; - } - walk_tree(&buf, el, false, false); - JSValue ret = JS_NewStringLen(ctx, buf.source, buf.length); - done_string(&buf); - - RETURN_JS(ret); -} - -static JSValue -js_element_get_property_textContent(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - struct string buf; - if (!init_string(&buf)) { - return JS_EXCEPTION; - } - walk_tree_content(&buf, el); - JSValue ret = JS_NewStringLen(ctx, buf.source, buf.length); - done_string(&buf); - - RETURN_JS(ret); -} - -static JSValue -js_element_set_property_className(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - assert(interpreter); - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_UNDEFINED; - } - size_t len; - const char *str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - xmlpp::ustring value = str; - el->set_attribute("class", value); - interpreter->changed = true; - JS_FreeCString(ctx, str); - - return JS_UNDEFINED; -} - -static JSValue -js_element_set_property_dir(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - assert(interpreter); - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_UNDEFINED; - } - size_t len; - const char *str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - xmlpp::ustring value = str; - - if (value == "ltr" || value == "rtl" || value == "auto") { - el->set_attribute("dir", value); - interpreter->changed = true; - } - JS_FreeCString(ctx, str); - - return JS_UNDEFINED; -} - -static JSValue -js_element_set_property_id(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - assert(interpreter); - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_UNDEFINED; - } - size_t len; - const char *str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - xmlpp::ustring value = str; - el->set_attribute("id", value); - interpreter->changed = true; - JS_FreeCString(ctx, str); - - return JS_UNDEFINED; -} - -static JSValue -js_element_set_property_innerHtml(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_UNDEFINED; - } - auto children = el->get_children(); - auto it = children.begin(); - auto end = children.end(); - - for (;it != end; ++it) { - xmlpp::Node::remove_node(*it); - } - xmlpp::ustring text = ""; - size_t len; - const char *str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - text += str; - text += ""; - JS_FreeCString(ctx, str); - - xmlDoc* doc = htmlReadDoc((xmlChar*)text.c_str(), NULL, "utf-8", HTML_PARSE_RECOVER | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING); - // Encapsulate raw libxml document in a libxml++ wrapper - xmlpp::Document doc1(doc); - - auto root = doc1.get_root_node(); - auto root1 = root->find("//root")[0]; - auto children2 = root1->get_children(); - auto it2 = children2.begin(); - auto end2 = children2.end(); - for (; it2 != end2; ++it2) { - el->import_node(*it2); - } - interpreter->changed = true; - - return JS_UNDEFINED; -} - -static JSValue -js_element_set_property_innerText(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_UNDEFINED; - } - auto children = el->get_children(); - auto it = children.begin(); - auto end = children.end(); - - for (;it != end; ++it) { - xmlpp::Node::remove_node(*it); - } - size_t len; - const char *str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - el->add_child_text(str); - interpreter->changed = true; - JS_FreeCString(ctx, str); - - return JS_UNDEFINED; -} - -static JSValue -js_element_set_property_lang(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_UNDEFINED; - } - size_t len; - const char *str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - xmlpp::ustring value = str; - el->set_attribute("lang", value); - interpreter->changed = true; - JS_FreeCString(ctx, str); - - return JS_UNDEFINED; -} - -static JSValue -js_element_set_property_title(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_UNDEFINED; - } - size_t len; - const char *str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - xmlpp::ustring value = str; - el->set_attribute("title", value); - interpreter->changed = true; - JS_FreeCString(ctx, str); - - return JS_UNDEFINED; -} - -// Common part of all add_child_element*() methods. -static xmlpp::Element* -el_add_child_element_common(xmlNode* child, xmlNode* node) -{ - if (!node) { - xmlFreeNode(child); - throw xmlpp::internal_error("Could not add child element node"); - } - xmlpp::Node::create_wrapper(node); - - return static_cast(node->_private); -} - -static void -check_contains(xmlpp::Node *node, xmlpp::Node *searched, bool *result_set, bool *result) -{ - if (*result_set) { - return; - } - - auto childs = node->get_children(); - auto it = childs.begin(); - auto end = childs.end(); - - for (; it != end; ++it) { - if (*it == searched) { - *result_set = true; - *result = true; - return; - } - check_contains(*it, searched, result_set, result); - } -} - -static JSValue -js_element_addEventListener(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct js_element_private *el_private = (struct js_element_private *)(JS_GetOpaque(this_val, js_element_class_id)); - - if (!el_private) { - return JS_NULL; - } - - if (argc < 2) { - return JS_UNDEFINED; - } - const char *str; - size_t len; - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - char *method = stracpy(str); - JS_FreeCString(ctx, str); - - if (!method) { - return JS_EXCEPTION; - } - - JSValue fun = argv[1]; - struct listener *l; - - foreach(l, el_private->listeners) { - if (strcmp(l->typ, method)) { - continue; - } - if (JS_VALUE_GET_PTR(l->fun) == JS_VALUE_GET_PTR(fun)) { - mem_free(method); - return JS_UNDEFINED; - } - } - struct listener *n = (struct listener *)mem_calloc(1, sizeof(*n)); - - if (n) { - n->typ = method; - n->fun = JS_DupValue(ctx, argv[1]); - add_to_list_end(el_private->listeners, n); - } - return JS_UNDEFINED; -} - -static JSValue -js_element_removeEventListener(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct js_element_private *el_private = (struct js_element_private *)(JS_GetOpaque(this_val, js_element_class_id)); - - if (!el_private) { - return JS_NULL; - } - - if (argc < 2) { - return JS_UNDEFINED; - } - const char *str; - size_t len; - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - char *method = stracpy(str); - JS_FreeCString(ctx, str); - - if (!method) { - return JS_EXCEPTION; - } - JSValue fun = argv[1]; - struct listener *l; - - foreach(l, el_private->listeners) { - if (strcmp(l->typ, method)) { - continue; - } - if (JS_VALUE_GET_PTR(l->fun) == JS_VALUE_GET_PTR(fun)) { - del_from_list(l); - mem_free_set(&l->typ, NULL); - mem_free(l); - mem_free(method); - return JS_UNDEFINED; - } - } - mem_free(method); - return JS_UNDEFINED; -} - - -static JSValue -js_element_appendChild(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#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); - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (argc != 1) { - return JS_NULL; - } - - if (!el) { - return JS_NULL; - } - xmlpp::Node *el2 = static_cast(js_getopaque(argv[0], js_element_class_id)); - el2 = el->import_node(el2); - interpreter->changed = true; - - return getElement(ctx, el2); -} - -static JSValue -js_element_cloneNode(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_NULL; - } - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - struct document_view *doc_view = interpreter->vs->doc_view; - struct document *document = doc_view->document; - - xmlpp::Document *doc2 = static_cast(document->dom); - xmlDoc *docu = doc2->cobj(); - xmlNode *xmlnode = xmlNewDocFragment(docu); - - if (!xmlnode) { - return JS_NULL; - } - xmlpp::Node *node = new(std::nothrow) xmlpp::Node(xmlnode); - - if (!node) { - return JS_NULL; - } - - try { - xmlpp::Node *node2 = node->import_node(el, JS_ToBool(ctx, argv[0])); - - if (!node2) { - return JS_NULL; - } - - return getElement(ctx, node2); - } catch (xmlpp::exception &e) { - return JS_NULL; - } -} - -static bool -isAncestor(xmlpp::Element *el, xmlpp::Node *node) -{ - while (node) { - if (el == node) { - return true; - } - node = node->get_parent(); - } - - return false; -} - -static JSValue -js_element_closest(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) { - return JS_UNDEFINED; - } - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_NULL; - } - const char *str; - size_t len; - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - xmlpp::ustring css = str; - xmlpp::ustring xpath = css2xpath(css); - JS_FreeCString(ctx, str); - - xmlpp::Node::NodeSet elements; - - try { - elements = el->find(xpath); - } catch (xmlpp::exception &e) { - return JS_NULL; - } - - if (elements.size() == 0) { - return JS_NULL; - } - - while (el) - { - for (auto node: elements) - { - if (isAncestor(el, node)) - { - return getElement(ctx, node); - } - } - el = el->get_parent(); - } - - return JS_NULL; -} - -static JSValue -js_element_contains(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; - } - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_FALSE; - } - xmlpp::Element *el2 = static_cast(js_getopaque(argv[0], js_element_class_id)); - - if (!el2) { - return JS_FALSE; - } - - bool result_set = false; - bool result = false; - - check_contains(el, el2, &result_set, &result); - - return JS_NewBool(ctx, result); -} - -static JSValue -js_element_getAttribute(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; - } - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_FALSE; - } - size_t len; - const char *str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_NULL; - } - xmlpp::ustring v = str; - xmlpp::Attribute *attr = el->get_attribute(v); - JS_FreeCString(ctx, str); - - if (!attr) { - return JS_NULL; - } - xmlpp::ustring val = attr->get_value(); - - JSValue r = JS_NewStringLen(ctx, val.c_str(), val.length()); - RETURN_JS(r); -} - -static JSValue -js_element_getAttributeNode(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; - } - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_UNDEFINED; - } - size_t len; - const char *str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_NULL; - } - xmlpp::ustring v = str; - xmlpp::Attribute *attr = el->get_attribute(v); - JS_FreeCString(ctx, str); - - return getAttr(ctx, attr); -} - -static JSValue -js_element_getElementsByTagName(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) { - return JS_FALSE; - } - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_UNDEFINED; - } - const char *str; - size_t len; - - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - xmlpp::ustring id = str; - JS_FreeCString(ctx, str); - std::transform(id.begin(), id.end(), id.begin(), ::tolower); - - xmlpp::ustring xpath = "//"; - xpath += id; - xmlpp::Node::NodeSet *elements = new(std::nothrow) xmlpp::Node::NodeSet; - - if (!elements) { - return JS_NULL; - } - *elements = el->find(xpath); - JSValue rr = getCollection(ctx, elements); - JS_FreeValue(ctx, rr); - - RETURN_JS(rr); -} - -static JSValue -js_element_hasAttribute(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; - } - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_FALSE; - } - size_t len; - const char *str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_NULL; - } - xmlpp::ustring v = str; - xmlpp::Attribute *attr = el->get_attribute(v); - JS_FreeCString(ctx, str); - - return JS_NewBool(ctx, (bool)attr); -} - -static JSValue -js_element_hasAttributes(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 != 0) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_UNDEFINED; - } - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_FALSE; - } - auto attrs = el->get_attributes(); - - return JS_NewBool(ctx, (bool)attrs.size()); -} - -static JSValue -js_element_hasChildNodes(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 != 0) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_UNDEFINED; - } - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_FALSE; - } - auto children = el->get_children(); - - return JS_NewBool(ctx, (bool)children.size()); -} - -static JSValue -js_element_insertBefore(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 != 2) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_UNDEFINED; - } - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_UNDEFINED; - } - - JSValue next_sibling1 = argv[1]; - JSValue child1 = argv[0]; - - xmlpp::Node *next_sibling = static_cast(js_getopaque(next_sibling1, js_element_class_id)); - - if (!next_sibling) { - return JS_NULL; - } - - xmlpp::Node *child = static_cast(js_getopaque(child1, js_element_class_id)); - auto node = xmlAddPrevSibling(next_sibling->cobj(), child->cobj()); - auto res = el_add_child_element_common(child->cobj(), node); - - interpreter->changed = true; - - return getElement(ctx, res); -} - -static JSValue -js_element_isEqualNode(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; - } - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_FALSE; - } - - JSValue node = argv[0]; - xmlpp::Element *el2 = static_cast(js_getopaque(node, js_element_class_id)); - - struct string first; - struct string second; - - if (!init_string(&first)) { - return JS_EXCEPTION; - } - if (!init_string(&second)) { - done_string(&first); - return JS_EXCEPTION; - } - - walk_tree(&first, el, false, true); - walk_tree(&second, el2, false, true); - - bool ret = !strcmp(first.source, second.source); - - done_string(&first); - done_string(&second); - - return JS_NewBool(ctx, ret); -} - -static JSValue -js_element_isSameNode(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; - } - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_FALSE; - } - JSValue node = argv[0]; - xmlpp::Element *el2 = static_cast(js_getopaque(node, js_element_class_id)); - - return JS_NewBool(ctx, (el == el2)); -} - -static JSValue -js_element_matches(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) { - return JS_UNDEFINED; - } - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_FALSE; - } - const char *str; - size_t len; - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - xmlpp::ustring css = str; - xmlpp::ustring xpath = css2xpath(css); - JS_FreeCString(ctx, str); - - xmlpp::Node::NodeSet elements; - - try { - elements = el->find(xpath); - } catch (xmlpp::exception &e) { - return JS_FALSE; - } - - for (auto node: elements) { - if (node == el) { - return JS_TRUE; - } - } - - return JS_FALSE; -} - -static JSValue -js_element_querySelector(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) { - return JS_UNDEFINED; - } - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_FALSE; - } - const char *str; - size_t len; - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - xmlpp::ustring css = str; - xmlpp::ustring xpath = css2xpath(css); - - JS_FreeCString(ctx, str); - xmlpp::Node::NodeSet elements; - - try { - elements = el->find(xpath); - } catch (xmlpp::exception &e) { - return JS_NULL; - } - - for (auto node: elements) - { - if (isAncestor(el, node)) - { - return getElement(ctx, node); - } - } - - return JS_NULL; -} - -static JSValue -js_element_querySelectorAll(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) { - return JS_FALSE; - } - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_FALSE; - } - const char *str; - size_t len; - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - xmlpp::ustring css = str; - xmlpp::ustring xpath = css2xpath(css); - JS_FreeCString(ctx, str); - - xmlpp::Node::NodeSet elements; - xmlpp::Node::NodeSet *res = new(std::nothrow) xmlpp::Node::NodeSet; - - if (!res) { - return JS_NULL; - } - - try { - elements = el->find(xpath); - } catch (xmlpp::exception &e) {} - - for (auto node: elements) - { - if (isAncestor(el, node)) { - res->push_back(node); - } - } - JSValue rr = getCollection(ctx, res); - JS_FreeValue(ctx, rr); - - RETURN_JS(rr); -} - -static JSValue -js_element_remove(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 != 0) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_UNDEFINED; - } - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_UNDEFINED; - } - - xmlpp::Node::remove_node(el); - interpreter->changed = true; - - return JS_UNDEFINED; -} - -static JSValue -js_element_removeChild(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; - } - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el || !JS_IsObject(argv[0])) { - return JS_NULL; - } - JSValue node = argv[0]; - auto children = el->get_children(); - auto it = children.begin(); - auto end = children.end(); - xmlpp::Element *el2 = static_cast(js_getopaque(node, js_element_class_id)); - - for (;it != end; ++it) { - if (*it == el2) { - xmlpp::Node::remove_node(el2); - interpreter->changed = true; - - return getElement(ctx, el2); - } - } - - return JS_NULL; -} - -static JSValue -js_element_replaceWith(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; - } - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el || !JS_IsObject(argv[0])) { - return JS_UNDEFINED; - } - JSValue replacement = argv[0]; - xmlpp::Node *rep = static_cast(js_getopaque(replacement, js_element_class_id)); - auto n = xmlAddPrevSibling(el->cobj(), rep->cobj()); - xmlpp::Node::create_wrapper(n); - xmlpp::Node::remove_node(el); - interpreter->changed = true; - - return JS_UNDEFINED; -} - -static JSValue -js_element_setAttribute(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 != 2) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_UNDEFINED; - } - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - xmlpp::Element *el = static_cast(js_getopaque(this_val, js_element_class_id)); - - if (!el) { - return JS_UNDEFINED; - } - const char *attr_c; - const char *value_c; - size_t len_attr, len_value; - attr_c = JS_ToCStringLen(ctx, &len_attr, argv[0]); - - if (!attr_c) { - return JS_EXCEPTION; - } - value_c = JS_ToCStringLen(ctx, &len_value, argv[1]); - - if (!value_c) { - JS_FreeCString(ctx, attr_c); - return JS_EXCEPTION; - } - - xmlpp::ustring attr = attr_c; - xmlpp::ustring value = value_c; - el->set_attribute(attr, value); - interpreter->changed = true; - JS_FreeCString(ctx, attr_c); - JS_FreeCString(ctx, value_c); - - return JS_UNDEFINED; -} - -static JSValue -js_element_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, "[element object]"); -} - -static const JSCFunctionListEntry js_element_proto_funcs[] = { - JS_CGETSET_DEF("attributes", js_element_get_property_attributes, nullptr), - JS_CGETSET_DEF("children", js_element_get_property_children, nullptr), - JS_CGETSET_DEF("childElementCount", js_element_get_property_childElementCount, nullptr), - JS_CGETSET_DEF("childNodes", js_element_get_property_childNodes, nullptr), - JS_CGETSET_DEF("className", js_element_get_property_className, js_element_set_property_className), - JS_CGETSET_DEF("dir", js_element_get_property_dir, js_element_set_property_dir), - JS_CGETSET_DEF("firstChild", js_element_get_property_firstChild, nullptr), - JS_CGETSET_DEF("firstElementChild", js_element_get_property_firstElementChild, nullptr), - JS_CGETSET_DEF("id", js_element_get_property_id, js_element_set_property_id), - JS_CGETSET_DEF("innerHTML", js_element_get_property_innerHtml, js_element_set_property_innerHtml), - JS_CGETSET_DEF("innerText", js_element_get_property_innerHtml, js_element_set_property_innerText), - JS_CGETSET_DEF("lang", js_element_get_property_lang, js_element_set_property_lang), - JS_CGETSET_DEF("lastChild", js_element_get_property_lastChild, nullptr), - JS_CGETSET_DEF("lastElementChild", js_element_get_property_lastElementChild, nullptr), - JS_CGETSET_DEF("nextElementSibling", js_element_get_property_nextElementSibling, nullptr), - JS_CGETSET_DEF("nextSibling", js_element_get_property_nextSibling, nullptr), - JS_CGETSET_DEF("nodeName", js_element_get_property_nodeName, nullptr), - JS_CGETSET_DEF("nodeType", js_element_get_property_nodeType, nullptr), - JS_CGETSET_DEF("nodeValue", js_element_get_property_nodeValue, nullptr), - JS_CGETSET_DEF("outerHTML", js_element_get_property_outerHtml, nullptr), - JS_CGETSET_DEF("ownerDocument", js_element_get_property_ownerDocument, nullptr), - JS_CGETSET_DEF("parentElement", js_element_get_property_parentElement, nullptr), - JS_CGETSET_DEF("parentNode", js_element_get_property_parentNode, nullptr), - JS_CGETSET_DEF("previousElementSibling", js_element_get_property_previousElementSibling, nullptr), - JS_CGETSET_DEF("previousSibling", js_element_get_property_previousSibling, nullptr), - JS_CGETSET_DEF("tagName", js_element_get_property_tagName, nullptr), - JS_CGETSET_DEF("textContent", js_element_get_property_textContent, nullptr), - JS_CGETSET_DEF("title", js_element_get_property_title, js_element_set_property_title), - JS_CFUNC_DEF("addEventListener", 3, js_element_addEventListener), - JS_CFUNC_DEF("appendChild", 1, js_element_appendChild), - JS_CFUNC_DEF("cloneNode", 1, js_element_cloneNode), - JS_CFUNC_DEF("closest", 1, js_element_closest), - JS_CFUNC_DEF("contains", 1, js_element_contains), - JS_CFUNC_DEF("getAttribute", 1, js_element_getAttribute), - JS_CFUNC_DEF("getAttributeNode",1, js_element_getAttributeNode), - JS_CFUNC_DEF("getElementsByTagName", 1, js_element_getElementsByTagName), - JS_CFUNC_DEF("hasAttribute", 1, js_element_hasAttribute), - JS_CFUNC_DEF("hasAttributes", 0, js_element_hasAttributes), - JS_CFUNC_DEF("hasChildNodes", 0, js_element_hasChildNodes), - JS_CFUNC_DEF("insertBefore", 2, js_element_insertBefore), - JS_CFUNC_DEF("isEqualNode", 1, js_element_isEqualNode), - JS_CFUNC_DEF("isSameNode", 1, js_element_isSameNode), - JS_CFUNC_DEF("matches",1, js_element_matches), - JS_CFUNC_DEF("querySelector",1, js_element_querySelector), - JS_CFUNC_DEF("querySelectorAll",1, js_element_querySelectorAll), - JS_CFUNC_DEF("remove", 0, js_element_remove), - JS_CFUNC_DEF("removeChild",1, js_element_removeChild), - JS_CFUNC_DEF("removeEventListener", 3, js_element_removeEventListener), - JS_CFUNC_DEF("replaceWith",1, js_element_replaceWith), - JS_CFUNC_DEF("setAttribute",2, js_element_setAttribute), - - JS_CFUNC_DEF("toString", 0, js_element_toString) -}; - -static std::map map_elements; - -static -void js_element_finalizer(JSRuntime *rt, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(val); - - struct js_element_private *el_private = (struct js_element_private *)JS_GetOpaque(val, js_element_class_id); - - if (el_private) { - struct listener *l; - - foreach(l, el_private->listeners) { - mem_free_set(&l->typ, NULL); - } - free_list(el_private->listeners); - - map_elements.erase(el_private->node); - mem_free(el_private); - } -} - -static void -js_element_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(val); - - struct js_element_private *el_private = (struct js_element_private *)JS_GetOpaque(val, js_element_class_id); - - if (el_private) { - JS_MarkValue(rt, el_private->thisval, mark_func); - - struct listener *l; - - foreach(l, el_private->listeners) { - JS_MarkValue(rt, l->fun, mark_func); - } - } -} - - -static JSClassDef js_element_class = { - "Element", - .finalizer = js_element_finalizer, - .gc_mark = js_element_mark, -}; - -int -js_element_init(JSContext *ctx) -{ - JSValue element_proto; - - /* create the element class */ - JS_NewClassID(&js_element_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_element_class_id, &js_element_class); - - JSValue global_obj = JS_GetGlobalObject(ctx); - REF_JS(global_obj); - - element_proto = JS_NewObject(ctx); - REF_JS(element_proto); - - JS_SetPropertyFunctionList(ctx, element_proto, js_element_proto_funcs, countof(js_element_proto_funcs)); - JS_SetClassProto(ctx, js_element_class_id, element_proto); - JS_SetPropertyStr(ctx, global_obj, "Element", JS_DupValue(ctx, element_proto)); - - JS_FreeValue(ctx, global_obj); - - return 0; -} - -static std::map map_privates; - -JSValue -getElement(JSContext *ctx, void *node) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - static int initialized; - /* create the element class */ - if (!initialized) { - JS_NewClassID(&js_element_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_element_class_id, &js_element_class); - initialized = 1; - map_elements.clear(); - } - - auto node_find = map_elements.find(node); - - if (node_find != map_elements.end()) { - JSValue r = JS_DupValue(ctx, node_find->second); - RETURN_JS(r); - } - - struct js_element_private *el_private = (struct js_element_private *)mem_calloc(1, sizeof(*el_private)); - - if (!el_private) { - return JS_NULL; - } - init_list(el_private->listeners); - el_private->node = node; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - el_private->interpreter = interpreter; - - JSValue element_obj = JS_NewObjectClass(ctx, js_element_class_id); - REF_JS(element_obj); - - JS_SetPropertyFunctionList(ctx, element_obj, js_element_proto_funcs, countof(js_element_proto_funcs)); - JS_SetClassProto(ctx, js_element_class_id, element_obj); - JS_SetOpaque(element_obj, el_private); - - map_elements[node] = element_obj; - map_privates[node] = el_private; - - JSValue rr = JS_DupValue(ctx, element_obj); - el_private->thisval = JS_DupValue(ctx, rr); - RETURN_JS(rr); -} - -void -check_element_event(void *elem, const char *event_name, struct term_event *ev) -{ - auto el = map_privates.find(elem); - - if (el == map_privates.end()) { - return; - } - struct js_element_private *el_private = el->second; - struct ecmascript_interpreter *interpreter = el_private->interpreter; - JSContext *ctx = (JSContext *)interpreter->backend_data; - interpreter->heartbeat = add_heartbeat(interpreter); - - struct listener *l; - - foreach(l, el_private->listeners) { - if (strcmp(l->typ, event_name)) { - continue; - } - if (ev && ev->ev == EVENT_KBD && (!strcmp(event_name, "keydown") || !strcmp(event_name, "keyup"))) { - JSValue func = JS_DupValue(ctx, l->fun); - JSValue arg = get_keyboardEvent(ctx, ev); - JSValue ret = JS_Call(ctx, func, el_private->thisval, 1, (JSValueConst *) &arg); - JS_FreeValue(ctx, ret); - JS_FreeValue(ctx, func); - JS_FreeValue(ctx, arg); - } else { - JSValue func = JS_DupValue(ctx, l->fun); - JSValue arg = JS_UNDEFINED; - JSValue ret = JS_Call(ctx, func, el_private->thisval, 1, (JSValueConst *) &arg); - JS_FreeValue(ctx, ret); - JS_FreeValue(ctx, func); - JS_FreeValue(ctx, arg); - } - } - done_heartbeat(interpreter->heartbeat); - check_for_rerender(interpreter, event_name); -} -#endif diff --git a/src/ecmascript/quickjs/form.cpp b/src/ecmascript/quickjs/form.cpp deleted file mode 100644 index 1500d3a5..00000000 --- a/src/ecmascript/quickjs/form.cpp +++ /dev/null @@ -1,1161 +0,0 @@ -/* The QuickJS form object implementation. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "elinks.h" - -#include "bfu/dialog.h" -#include "cache/cache.h" -#include "cookies/cookies.h" -#include "dialogs/menu.h" -#include "dialogs/status.h" -#include "document/html/frames.h" -#include "document/document.h" -#include "document/forms.h" -#include "document/view.h" -#include "ecmascript/ecmascript.h" -#include "ecmascript/quickjs.h" -#include "ecmascript/quickjs/document.h" -#include "ecmascript/quickjs/form.h" -#include "ecmascript/quickjs/forms.h" -#include "ecmascript/quickjs/input.h" -#include "ecmascript/quickjs/window.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/memory.h" -#include "util/string.h" -#include "viewer/text/draw.h" -#include "viewer/text/form.h" -#include "viewer/text/link.h" -#include "viewer/text/vs.h" - -#include -#include - -#ifndef CONFIG_LIBDOM - -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -static JSClassID js_form_class_id; -static JSClassID js_form_elements_class_id; - -static std::map map_form_elements; -static std::map map_elements_form; -static std::map map_form; -static std::map map_rev_form; - -JSValue getForm(JSContext *ctx, struct form *form); - -static struct form_view * -getOpaque(JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - return (struct form_view *)JS_GetOpaque(this_val, js_form_elements_class_id); -} - -static void -setOpaque(JSValueConst this_val, struct form_view *fv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - if (!fv) { - map_elements_form.erase(this_val); - } else { - map_elements_form[this_val] = fv; - } - JS_SetOpaque(this_val, fv); -} - -static struct form * -form_GetOpaque(JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - return map_rev_form[this_val]; -} - -static void -form_SetOpaque(JSValueConst this_val, struct form *form) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - if (!form) { - map_rev_form.erase(this_val); - } else { - map_rev_form[this_val] = form; - } -} - -static JSValue -js_get_form_control_object(JSContext *ctx, - enum form_type type, struct form_state *fs) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - switch (type) { - case FC_TEXT: - case FC_PASSWORD: - case FC_FILE: - case FC_CHECKBOX: - case FC_RADIO: - case FC_SUBMIT: - case FC_IMAGE: - case FC_RESET: - case FC_BUTTON: - case FC_HIDDEN: - case FC_SELECT: - return js_get_input_object(ctx, fs); - - case FC_TEXTAREA: - /* TODO */ - return JS_NULL; - - default: - INTERNAL("Weird fc->type %d", type); - return JS_NULL; - } -} - -static void -js_form_set_items(JSContext *ctx, JSValueConst this_val, void *node) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_view *form_view; - struct form *form; - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - doc_view = vs->doc_view; - document = doc_view->document; - - form_view = (struct form_view *)node; - if (!form_view) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return; /* detached */ - } - form = find_form_by_form_view(document, form_view); - - int counter = 0; - struct el_form_control *fc; - foreach (fc, form->items) { - struct form_state *fs = find_form_state(doc_view, fc); - - if (!fs) { - continue; - } - - JSValue obj = js_get_form_control_object(ctx, fc->type, fs); - REF_JS(obj); - - JS_SetPropertyUint32(ctx, this_val, counter, JS_DupValue(ctx, obj)); - - if (fc->id) { - if (strcmp(fc->id, "item") && strcmp(fc->id, "namedItem")) { - JS_SetPropertyStr(ctx, this_val, fc->id, JS_DupValue(ctx, obj)); - } - } else if (fc->name) { - if (strcmp(fc->name, "item") && strcmp(fc->name, "namedItem")) { - JS_SetPropertyStr(ctx, this_val, fc->name, JS_DupValue(ctx, obj)); - } - } - JS_FreeValue(ctx, obj); - counter++; - } -} - -static void -js_form_set_items2(JSContext *ctx, JSValueConst this_val, void *node) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct form *form; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - doc_view = vs->doc_view; - form = (struct form *)node; - - int counter = 0; - struct el_form_control *fc; - foreach (fc, form->items) { - struct form_state *fs = find_form_state(doc_view, fc); - - if (!fs) { - continue; - } - - JSValue obj = js_get_form_control_object(ctx, fc->type, fs); - REF_JS(obj); - - JS_SetPropertyUint32(ctx, this_val, counter, JS_DupValue(ctx, obj)); - - if (fc->id) { - if (strcmp(fc->id, "item") && strcmp(fc->id, "namedItem")) { - JS_SetPropertyStr(ctx, this_val, fc->id, JS_DupValue(ctx, obj)); - } - } else if (fc->name) { - if (strcmp(fc->name, "item") && strcmp(fc->name, "namedItem")) { - JS_SetPropertyStr(ctx, this_val, fc->name, JS_DupValue(ctx, obj)); - } - } - JS_FreeValue(ctx, obj); - counter++; - } -} - -static JSValue -js_form_elements_get_property_length(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_view *form_view; - struct form *form; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_UNDEFINED; - } - - doc_view = vs->doc_view; - document = doc_view->document; - - form_view = getOpaque(this_val); - if (!form_view) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_UNDEFINED; /* detached */ - } - form = find_form_by_form_view(document, form_view); - - return JS_NewInt32(ctx, list_size(&form->items)); -} - -static JSValue -js_form_elements_item2(JSContext *ctx, JSValueConst this_val, int index) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_view *form_view; - struct form *form; - struct el_form_control *fc; - int counter = -1; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - doc_view = vs->doc_view; - document = doc_view->document; - form_view = getOpaque(this_val); - - if (!form_view) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - form = find_form_by_form_view(document, form_view); - foreach (fc, form->items) { - counter++; - - if (counter == index) { - struct form_state *fs = find_form_state(doc_view, fc); - - if (fs) { - return js_get_form_control_object(ctx, fc->type, fs); - } - } - } - - return JS_UNDEFINED; -} - -/* @form_elements_funcs{"item"} */ -static JSValue -js_form_elements_item(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) { - return JS_NULL; - } - - int index; - - if (JS_ToInt32(ctx, &index, argv[0])) { - return JS_NULL; - } - - return js_form_elements_item2(ctx, this_val, index); -} - -static JSValue -js_form_elements_namedItem2(JSContext *ctx, JSValueConst this_val, const char *string) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_view *form_view; - struct form *form; - struct el_form_control *fc; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - - if (!*string) { - return JS_UNDEFINED; - } - vs = interpreter->vs; - doc_view = vs->doc_view; - document = doc_view->document; - form_view = getOpaque(this_val); - - if (!form_view) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - form = find_form_by_form_view(document, form_view); - - foreach (fc, form->items) { - if ((fc->id && !c_strcasecmp(string, fc->id)) - || (fc->name && !c_strcasecmp(string, fc->name))) { - struct form_state *fs = find_form_state(doc_view, fc); - - if (fs) { - return js_get_form_control_object(ctx, fc->type, fs); - } - } - } - - return JS_UNDEFINED; -} - -/* @form_elements_funcs{"namedItem"} */ -static JSValue -js_form_elements_namedItem(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) { - return JS_NULL; - } - - const char *str; - size_t len; - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - JSValue ret = js_form_elements_namedItem2(ctx, this_val, str); - JS_FreeCString(ctx, str); - - RETURN_JS(ret); -} - -static JSValue -js_form_elements_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, "[form elements object]"); -} - -#if 0 -static struct form_view * -js_form_get_form_view(JSContext *ctx, JSValueConst this_val, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct form_view *fv = getOpaque(this_val); - - return fv; -} -#endif - -static JSValue -js_form_get_property_action(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct form *form; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_UNDEFINED; - } - form = form_GetOpaque(this_val); - assert(form); - - JSValue r = JS_NewString(ctx, form->action); - RETURN_JS(r); -} - -static JSValue -js_form_set_property_action(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct view_state *vs; - struct form *form; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_UNDEFINED; - } - form = form_GetOpaque(this_val); - assert(form); - - const char *str; - char *string; - size_t len; - - str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - - string = stracpy(str); - JS_FreeCString(ctx, str); - - if (form->action) { - ecmascript_set_action(&form->action, string); - } else { - mem_free_set(&form->action, string); - } - - return JS_UNDEFINED; -} - -static const JSCFunctionListEntry js_form_elements_proto_funcs[] = { - JS_CGETSET_DEF("length", js_form_elements_get_property_length, nullptr), - JS_CFUNC_DEF("item", 1, js_form_elements_item), - JS_CFUNC_DEF("namedItem", 1, js_form_elements_namedItem), - JS_CFUNC_DEF("toString", 0, js_form_elements_toString) -}; - -void -quickjs_detach_form_view(struct form_view *fv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - JSValue jsform = fv->ecmascript_obj; - - if (!JS_IsNull(jsform)) { - map_form_elements.erase(fv); - setOpaque(jsform, nullptr); - fv->ecmascript_obj = JS_NULL; - } -} - -static -void js_elements_finalizer(JSRuntime *rt, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(val); - - struct form_view *fv = getOpaque(val); - - setOpaque(val, nullptr); - fv->ecmascript_obj = JS_NULL; - map_form_elements.erase(fv); -} - -static JSClassDef js_form_elements_class = { - "elements", - js_elements_finalizer -}; - -JSValue -getFormElements(JSContext *ctx, struct form_view *fv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - auto node_find = map_form_elements.find(fv); - - if (node_find != map_form_elements.end()) { - JSValue r = JS_DupValue(ctx, node_find->second); - RETURN_JS(r); - } - JS_NewClassID(&js_form_elements_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_form_elements_class_id, &js_form_elements_class); - - JSValue form_elements_obj = JS_NewObjectClass(ctx, js_form_elements_class_id); - - JS_SetPropertyFunctionList(ctx, form_elements_obj, js_form_elements_proto_funcs, countof(js_form_elements_proto_funcs)); - setOpaque(form_elements_obj, fv); - fv->ecmascript_obj = form_elements_obj; - js_form_set_items(ctx, form_elements_obj, fv); - map_form_elements[fv] = form_elements_obj; - - RETURN_JS(form_elements_obj); -} - -static JSValue -js_form_get_property_elements(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; - - struct form *form = form_GetOpaque(this_val); - assert(form); - - struct form_view *fv = nullptr; - bool found = false; - - foreach (fv, vs->forms) { - if (form->form_num == fv->form_num) { - found = true; - break; - } - } - - if (!found || !fv) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - - return getFormElements(ctx, fv); -} - -static JSValue -js_form_get_property_encoding(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct form *form; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - form = form_GetOpaque(this_val); - assert(form); - - JSValue r; - - switch (form->method) { - case FORM_METHOD_GET: - case FORM_METHOD_POST: - r = JS_NewString(ctx, "application/x-www-form-urlencoded"); - RETURN_JS(r); - case FORM_METHOD_POST_MP: - r = JS_NewString(ctx, "multipart/form-data"); - RETURN_JS(r); - case FORM_METHOD_POST_TEXT_PLAIN: - r = JS_NewString(ctx, "text/plain"); - RETURN_JS(r); - } - - return JS_UNDEFINED; -} - -/* @form_class.setProperty */ -static JSValue -js_form_set_property_encoding(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct view_state *vs; - struct form *form; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_UNDEFINED; - } - form = form_GetOpaque(this_val); - assert(form); - const char *str; - size_t len; - - str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - - if (!c_strcasecmp(str, "application/x-www-form-urlencoded")) { - form->method = form->method == FORM_METHOD_GET ? FORM_METHOD_GET - : FORM_METHOD_POST; - } else if (!c_strcasecmp(str, "multipart/form-data")) { - form->method = FORM_METHOD_POST_MP; - } else if (!c_strcasecmp(str, "text/plain")) { - form->method = FORM_METHOD_POST_TEXT_PLAIN; - } - JS_FreeCString(ctx, str); - - return JS_UNDEFINED; -} - -static JSValue -js_form_get_property_length(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct form *form; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_UNDEFINED; - } - form = form_GetOpaque(this_val); - assert(form); - - return JS_NewInt32(ctx, list_size(&form->items)); -} - -static JSValue -js_form_get_property_method(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct form *form; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_UNDEFINED; - } - form = form_GetOpaque(this_val); - assert(form); - - JSValue r; - - switch (form->method) { - case FORM_METHOD_GET: - r = JS_NewStringLen(ctx, "GET", 3); - RETURN_JS(r); - - case FORM_METHOD_POST: - case FORM_METHOD_POST_MP: - case FORM_METHOD_POST_TEXT_PLAIN: - r = JS_NewStringLen(ctx, "POST", 4); - RETURN_JS(r); - } - - return JS_UNDEFINED; -} - -/* @form_class.setProperty */ -static JSValue -js_form_set_property_method(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct view_state *vs; - struct form *form; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_UNDEFINED; - } - form = form_GetOpaque(this_val); - assert(form); - const char *str; - size_t len; - - str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - - if (!c_strcasecmp(str, "GET")) { - form->method = FORM_METHOD_GET; - } else if (!c_strcasecmp(str, "POST")) { - form->method = FORM_METHOD_POST; - } - JS_FreeCString(ctx, str); - - return JS_UNDEFINED; -} - -static JSValue -js_form_get_property_name(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct form *form; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_UNDEFINED; - } - form = form_GetOpaque(this_val); - assert(form); - - JSValue r = JS_NewString(ctx, form->name); - RETURN_JS(r); -} - -/* @form_class.setProperty */ -static JSValue -js_form_set_property_name(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct view_state *vs; - struct form *form; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_UNDEFINED; - } - form = form_GetOpaque(this_val); - assert(form); - - const char *str; - size_t len; - str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - mem_free_set(&form->name, stracpy(str)); - JS_FreeCString(ctx, str); - - return JS_UNDEFINED; -} - -static JSValue -js_form_get_property_target(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct form *form; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_UNDEFINED; - } - form = form_GetOpaque(this_val); - assert(form); - - JSValue r = JS_NewString(ctx, form->target); - RETURN_JS(r); -} - -static JSValue -js_form_set_property_target(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct view_state *vs; - struct form *form; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_UNDEFINED; - } - form = form_GetOpaque(this_val); - assert(form); - - const char *str; - size_t len; - str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - mem_free_set(&form->target, stracpy(str)); - JS_FreeCString(ctx, str); - - return JS_UNDEFINED; -} - -/* @form_funcs{"reset"} */ -static JSValue -js_form_reset(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct form *form; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - doc_view = vs->doc_view; - form = form_GetOpaque(this_val); - assert(form); - - do_reset_form(doc_view, form); - draw_forms(doc_view->session->tab->term, doc_view); - - return JS_FALSE; -} - -/* @form_funcs{"submit"} */ -static JSValue -js_form_submit(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct session *ses; - struct form *form; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - doc_view = vs->doc_view; - ses = doc_view->session; - - form = form_GetOpaque(this_val); - assert(form); - submit_given_form(ses, doc_view, form, 0); - - return JS_FALSE; -} - -static JSValue -js_form_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, "[form object]"); -} - -JSValue -js_get_form_object(JSContext *ctx, JSValueConst jsdoc, struct form *form) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(jsdoc); - - return getForm(ctx, form); -} - -#if 0 -static JSValue -js_elements_ctor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv) -{ - 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"); - - if (JS_IsException(proto)) { - goto fail; - } - obj = JS_NewObjectProtoClass(ctx, proto, js_form_elements_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_elements_init(JSContext *ctx, JSValue global_obj) -{ - JSValue elements_proto, elements_class; - - /* create the elements class */ - JS_NewClassID(&js_form_elements_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_form_elements_class_id, &js_form_elements_class); - - elements_proto = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, elements_proto, js_form_elements_proto_funcs, countof(js_form_elements_proto_funcs)); - - elements_class = JS_NewCFunction2(ctx, js_elements_ctor, "elements", 0, JS_CFUNC_constructor, 0); - /* set proto.constructor and ctor.prototype */ - JS_SetConstructor(ctx, elements_class, elements_proto); - JS_SetClassProto(ctx, js_form_elements_class_id, elements_proto); - - JS_SetPropertyStr(ctx, global_obj, "elements", elements_proto); - return 0; -} -#endif - -static const JSCFunctionListEntry js_form_proto_funcs[] = { - JS_CGETSET_DEF("action", js_form_get_property_action, js_form_set_property_action), - JS_CGETSET_DEF("elements", js_form_get_property_elements, nullptr), - JS_CGETSET_DEF("encoding", js_form_get_property_encoding, js_form_set_property_encoding), - JS_CGETSET_DEF("length", js_form_get_property_length, nullptr), - JS_CGETSET_DEF("method", js_form_get_property_method, js_form_set_property_method), - JS_CGETSET_DEF("name", js_form_get_property_name, js_form_set_property_name), - JS_CGETSET_DEF("target", js_form_get_property_target, js_form_set_property_target), - JS_CFUNC_DEF("reset", 0, js_form_reset), - JS_CFUNC_DEF("submit", 0, js_form_submit), - JS_CFUNC_DEF("toString", 0, js_form_toString) -}; - - -static -void js_form_finalizer(JSRuntime *rt, JSValue val) -{ - REF_JS(val); - - struct form *form = form_GetOpaque(val); - - form_SetOpaque(val, nullptr); - form->ecmascript_obj = JS_NULL; - map_form.erase(form); -} - -static JSClassDef js_form_class = { - "form", - js_form_finalizer -}; - -#if 0 -static JSValue -js_form_ctor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv) -{ - 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"); - - if (JS_IsException(proto)) { - goto fail; - } - obj = JS_NewObjectProtoClass(ctx, proto, js_form_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_form_init(JSContext *ctx, JSValue global_obj) -{ - JSValue form_proto, form_class; - - /* create the form class */ - JS_NewClassID(&js_form_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_form_class_id, &js_form_class); - - form_proto = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, form_proto, js_form_proto_funcs, countof(js_form_proto_funcs)); - - form_class = JS_NewCFunction2(ctx, js_form_ctor, "form", 0, JS_CFUNC_constructor, 0); - /* set proto.constructor and ctor.prototype */ - JS_SetConstructor(ctx, form_class, form_proto); - JS_SetClassProto(ctx, js_form_class_id, form_proto); - - JS_SetPropertyStr(ctx, global_obj, "form", form_proto); - return 0; -} -#endif - -JSValue -getForm(JSContext *ctx, struct form *form) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - auto node_find = map_form.find(form); - - if (node_find != map_form.end()) { - JSValue r = JS_DupValue(ctx, node_find->second); - RETURN_JS(r); - } - JS_NewClassID(&js_form_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_form_class_id, &js_form_class); - - JSValue form_obj = JS_NewObjectClass(ctx, js_form_class_id); - - JS_SetPropertyFunctionList(ctx, form_obj, js_form_proto_funcs, countof(js_form_proto_funcs)); - form_SetOpaque(form_obj, form); - js_form_set_items2(ctx, form_obj, form); - form->ecmascript_obj = form_obj; - - map_form[form] = form_obj; - - RETURN_JS(form_obj); -} -#endif diff --git a/src/ecmascript/quickjs/forms.cpp b/src/ecmascript/quickjs/forms.cpp deleted file mode 100644 index 24646f35..00000000 --- a/src/ecmascript/quickjs/forms.cpp +++ /dev/null @@ -1,360 +0,0 @@ -/* The SpiderMonkey window object implementation. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "elinks.h" - -#include "bfu/dialog.h" -#include "cache/cache.h" -#include "cookies/cookies.h" -#include "dialogs/menu.h" -#include "dialogs/status.h" -#include "document/html/frames.h" -#include "document/document.h" -#include "document/forms.h" -#include "document/view.h" -#include "ecmascript/ecmascript.h" -#include "ecmascript/quickjs.h" -#include "ecmascript/quickjs/document.h" -#include "ecmascript/quickjs/form.h" -#include "ecmascript/quickjs/forms.h" -#include "ecmascript/quickjs/input.h" -#include "ecmascript/quickjs/window.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/memory.h" -#include "util/string.h" -#include "viewer/text/draw.h" -#include "viewer/text/form.h" -#include "viewer/text/link.h" -#include "viewer/text/vs.h" - -#include -#include - -#ifndef CONFIG_LIBDOM - -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -static std::map map_forms; -static std::map map_rev_forms; - -#if 0 -static void * -forms_GetOpaque(JSValueConst this_val) -{ - return map_rev_forms[this_val]; -} -#endif - -static void -forms_SetOpaque(JSValueConst this_val, void *node) -{ - REF_JS(this_val); - - if (!node) { - map_rev_forms.erase(this_val); - } else { - map_rev_forms[this_val] = node; - } -} - -/* Find the form whose name is @name, which should normally be a - * string (but might not be). */ -static JSValue -js_find_form_by_name(JSContext *ctx, - struct document_view *doc_view, - const char *string) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - struct form *form; - - if (!*string) - return JS_NULL; - - foreach (form, doc_view->document->forms) { - if (form->name && !c_strcasecmp(string, form->name)) { - return js_get_form_object(ctx, JS_NULL, form); - } - } - - return JS_NULL; -} - -static void -js_forms_set_items(JSContext *ctx, JSValueConst this_val, void *node) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - doc_view = vs->doc_view; - struct document *document = doc_view->document; - int counter = 0; - struct form_view *fv; - - foreach (fv, vs->forms) { - struct form *form = find_form_by_form_view(document, fv); - JSValue v = js_get_form_object(ctx, JS_NULL, form); - - REF_JS(v); - - JS_SetPropertyUint32(ctx, this_val, counter, JS_DupValue(ctx, v)); - - if (form->name) { - if (strcmp(form->name, "item") && strcmp(form->name, "namedItem")) { - JS_SetPropertyStr(ctx, this_val, form->name, JS_DupValue(ctx, v)); - } - } - JS_FreeValue(ctx, v); - counter++; - } -} - -static JSValue -js_forms_get_property_length(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; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_UNDEFINED; - } - struct document_view *doc_view = vs->doc_view; - struct document *document = doc_view->document; - - return JS_NewInt32(ctx, list_size(&document->forms)); -} - -static JSValue -js_forms_item2(JSContext *ctx, JSValueConst this_val, int index) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct form_view *fv; - int counter = -1; - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - - vs = interpreter->vs; - struct document_view *doc_view = vs->doc_view; - struct document *document = doc_view->document; - - foreach (fv, vs->forms) { - counter++; - if (counter == index) { - struct form *form = find_form_by_form_view(document, fv); - - return js_get_form_object(ctx, JS_NULL, form); - } - } - - return JS_UNDEFINED; -} - -/* @forms_funcs{"item"} */ -static JSValue -js_forms_item(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) { - return JS_UNDEFINED; - } - int index; - - if (JS_ToInt32(ctx, &index, argv[0])) { - return JS_UNDEFINED; - } - - return js_forms_item2(ctx, this_val, index); -} - -/* @forms_funcs{"namedItem"} */ -static JSValue -js_forms_namedItem(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) { - return JS_UNDEFINED; - } - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - struct view_state *vs = interpreter->vs; - struct document_view *doc_view = vs->doc_view; - const char *str; - size_t len; - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - JSValue ret = js_find_form_by_name(ctx, doc_view, str); - JS_FreeCString(ctx, str); - - RETURN_JS(ret); -} - -#if 0 -JSString * -unicode_to_jsstring(JSContext *ctx, unicode_val_T u) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - char16_t buf[2]; - - /* This is supposed to make a string from which - * jsval_to_accesskey() can get the original @u back. - * If @u is a surrogate, then that is not possible, so - * return NULL to indicate an error instead. - * - * If JS_NewUCStringCopyN hits a null character, it truncates - * the string there and pads it with more nulls. However, - * that is not a problem here, because if there is a null - * character in buf[], then it must be the only character. */ - if (u <= 0xFFFF && !is_utf16_surrogate(u)) { - buf[0] = u; - return JS_NewUCStringCopyN(ctx, buf, 1); - } else if (needs_utf16_surrogates(u)) { - buf[0] = get_utf16_high_surrogate(u); - buf[1] = get_utf16_low_surrogate(u); - return JS_NewUCStringCopyN(ctx, buf, 2); - } else { - return NULL; - } -} -#endif - -static JSValue -js_forms_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, "[forms object]"); -} - -static const JSCFunctionListEntry js_forms_proto_funcs[] = { - JS_CGETSET_DEF("length", js_forms_get_property_length, nullptr), - JS_CFUNC_DEF("item", 1, js_forms_item), - JS_CFUNC_DEF("namedItem", 1, js_forms_namedItem), - JS_CFUNC_DEF("toString", 0, js_forms_toString) -}; - -#if 0 -static JSValue -js_forms_ctor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv) -{ - 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"); - - if (JS_IsException(proto)) { - goto fail; - } - obj = JS_NewObjectProtoClass(ctx, proto, js_forms_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_forms_init(JSContext *ctx, JSValue global_obj) -{ - JSValue forms_proto, forms_class; - - /* create the forms class */ - JS_NewClassID(&js_forms_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_forms_class_id, &js_forms_class); - - forms_proto = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, forms_proto, js_forms_proto_funcs, countof(js_forms_proto_funcs)); - - forms_class = JS_NewCFunction2(ctx, js_forms_ctor, "forms", 0, JS_CFUNC_constructor, 0); - /* set proto.constructor and ctor.prototype */ - JS_SetConstructor(ctx, forms_class, forms_proto); - JS_SetClassProto(ctx, js_forms_class_id, forms_proto); - - JS_SetPropertyStr(ctx, global_obj, "forms", forms_proto); - return 0; -} -#endif - -JSValue -getForms(JSContext *ctx, void *node) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - auto node_find = map_forms.find(node); - - if (node_find != map_forms.end()) { - JSValue r = JS_DupValue(ctx, node_find->second); - RETURN_JS(r); - } - JSValue forms_obj = JS_NewArray(ctx); - JS_SetPropertyFunctionList(ctx, forms_obj, js_forms_proto_funcs, countof(js_forms_proto_funcs)); - forms_SetOpaque(forms_obj, node); - js_forms_set_items(ctx, forms_obj, node); - map_forms[node] = forms_obj; - - JSValue rr = JS_DupValue(ctx, forms_obj); - RETURN_JS(rr); -} -#endif diff --git a/src/ecmascript/quickjs/heartbeat.cpp b/src/ecmascript/quickjs/heartbeat.cpp deleted file mode 100644 index 10e4e8cf..00000000 --- a/src/ecmascript/quickjs/heartbeat.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* The QuickJS ECMAScript backend heartbeat fuctionality. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include /* setitimer(2) */ -#include - -#include "elinks.h" - -#include "config/options.h" -#include "document/view.h" -#include "ecmascript/ecmascript.h" -#include "ecmascript/quickjs.h" -#include "ecmascript/quickjs/heartbeat.h" -#include "osdep/signals.h" -#include "session/session.h" -#include "util/lists.h" -#include "util/math.h" /* int_upper_bound */ -#include "util/memory.h" -#include "viewer/text/vs.h" - -#ifndef CONFIG_LIBDOM - -static INIT_LIST_OF(struct heartbeat, heartbeats); - -static struct itimerval heartbeat_timer = { { 1, 0 }, { 1, 0 } }; - -/* This callback is installed by JS_SetInterruptHandler. - * Returning 1 terminates script execution immediately. */ - -int -js_heartbeat_callback(JSRuntime *rt, void *opaque) -{ - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)opaque; - - if (!interpreter || !interpreter->heartbeat || interpreter->heartbeat->ttl > 0) { - return 0; - } - return 1; -} - -/* Callback for SIGVTALRM. Go through all heartbeats, decrease each - * one's TTL, and call JS_RequestInterruptCallback if a heartbeat's TTL - * goes to 0. */ -void -check_heartbeats(void *data) -{ - struct heartbeat *hb; - - foreach (hb, heartbeats) { - assert(hb->interpreter); - --hb->ttl; - - if (hb->ttl <= 0) { - if (hb->interpreter->vs - && hb->interpreter->vs->doc_view - && hb->interpreter->vs->doc_view->session - && hb->interpreter->vs->doc_view->session->tab - && hb->interpreter->vs->doc_view->session->tab->term) { - struct session *ses = hb->interpreter->vs->doc_view->session; - struct terminal *term = ses->tab->term; - int max_exec_time = get_opt_int("ecmascript.max_exec_time", ses); - - ecmascript_timeout_dialog(term, max_exec_time); - } - } - } -#ifndef CONFIG_OS_DOS - install_signal_handler(SIGVTALRM, check_heartbeats, NULL, 1); -#endif -} - -/* Create a new heartbeat for the given interpreter. */ -struct heartbeat * -add_heartbeat(struct ecmascript_interpreter *interpreter) -{ - struct session *ses; - struct heartbeat *hb; - - assert(interpreter); - - if (!interpreter->vs || !interpreter->vs->doc_view) - ses = NULL; - else - ses = interpreter->vs->doc_view->session; - hb = (struct heartbeat *)mem_alloc(sizeof(struct heartbeat)); - - if (!hb) return NULL; - - hb->ttl = get_opt_int("ecmascript.max_exec_time", ses); - hb->interpreter = interpreter; - add_to_list(heartbeats, hb); - -#ifndef CONFIG_OS_DOS - /* Update the heartbeat timer. */ - if (list_is_singleton(*hb)) { - heartbeat_timer.it_value.tv_sec = 1; - setitimer(ITIMER_VIRTUAL, &heartbeat_timer, NULL); - } - - /* We install the handler every call to add_heartbeat instead of only on - * module initialisation because other code may set other handlers for - * the signal. */ - install_signal_handler(SIGVTALRM, check_heartbeats, NULL, 1); -#endif - return hb; -} - -/* Destroy the given heartbeat. */ -void -done_heartbeat(struct heartbeat *hb) -{ - if (!hb) return; /* add_heartbeat returned NULL */ - assert(hb->interpreter); - -#ifndef CONFIG_OS_DOS - /* Stop the heartbeat timer if this heartbeat is the only one. */ - if (list_is_singleton(*hb)) { - heartbeat_timer.it_value.tv_sec = 0; - setitimer(ITIMER_VIRTUAL, &heartbeat_timer, NULL); - } -#endif - - del_from_list(hb); - hb->interpreter->heartbeat = NULL; - mem_free(hb); -} -#endif diff --git a/src/ecmascript/quickjs/history.cpp b/src/ecmascript/quickjs/history.cpp deleted file mode 100644 index 7435d985..00000000 --- a/src/ecmascript/quickjs/history.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/* The QuickJS history object implementation. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "elinks.h" - -#include "bfu/dialog.h" -#include "cache/cache.h" -#include "cookies/cookies.h" -#include "dialogs/menu.h" -#include "dialogs/status.h" -#include "document/html/frames.h" -#include "document/document.h" -#include "document/forms.h" -#include "document/view.h" -#include "ecmascript/ecmascript.h" -#include "ecmascript/quickjs.h" -#include "ecmascript/quickjs/history.h" -#include "ecmascript/quickjs/window.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/memory.h" -#include "util/string.h" -#include "viewer/text/draw.h" -#include "viewer/text/form.h" -#include "viewer/text/link.h" -#include "viewer/text/vs.h" - -#ifndef CONFIG_LIBDOM - -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -static JSClassID js_history_class_id; - -/* @history_funcs{"back"} */ -static JSValue -js_history_back(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#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); - assert(interpreter); - struct document_view *doc_view = interpreter->vs->doc_view; - struct session *ses = doc_view->session; - - go_back(ses); - -/* history_back() must return 0 for onClick to cause displaying previous page - * and return non zero for to prevent - * "calculating" new link. Returned value 2 is changed to 0 in function - * spidermonkey_eval_boolback */ - return JS_NULL; -} - -/* @history_funcs{"forward"} */ -static JSValue -js_history_forward(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#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); - assert(interpreter); - struct document_view *doc_view = interpreter->vs->doc_view; - struct session *ses = doc_view->session; - - go_unback(ses); - - return JS_NULL; -} - -/* @history_funcs{"go"} */ -static JSValue -js_history_go(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#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); - assert(interpreter); - struct document_view *doc_view = interpreter->vs->doc_view; - struct session *ses = doc_view->session; - struct location *loc; - - if (argc != 1) { - return JS_UNDEFINED; - } - - int index; - if (JS_ToInt32(ctx, &index, argv[0])) { - return JS_UNDEFINED; - } - - for (loc = cur_loc(ses); - loc != (struct location *) &ses->history.history; - loc = index > 0 ? loc->next : loc->prev) { - if (!index) { - go_history(ses, loc); - break; - } - - index += index > 0 ? -1 : 1; - } - - return JS_NULL; -} - -static JSValue -js_history_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, "[history object]"); -} - -static const JSCFunctionListEntry js_history_funcs[] = { - JS_CFUNC_DEF("back", 0, js_history_back ), - JS_CFUNC_DEF("forward", 0, js_history_forward ), - JS_CFUNC_DEF("go", 1, js_history_go ), - JS_CFUNC_DEF("toString", 0, js_history_toString) -}; - -static JSClassDef js_history_class = { - "history", -}; - -int -js_history_init(JSContext *ctx) -{ - JSValue history_proto; - - /* create the history class */ - JS_NewClassID(&js_history_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_history_class_id, &js_history_class); - - JSValue global_obj = JS_GetGlobalObject(ctx); - REF_JS(global_obj); - - history_proto = JS_NewObject(ctx); - REF_JS(history_proto); - - JS_SetPropertyFunctionList(ctx, history_proto, js_history_funcs, countof(js_history_funcs)); - JS_SetClassProto(ctx, js_history_class_id, history_proto); - JS_SetPropertyStr(ctx, global_obj, "history", JS_DupValue(ctx, history_proto)); - - JS_FreeValue(ctx, global_obj); - - return 0; -} -#endif diff --git a/src/ecmascript/quickjs/implementation.cpp b/src/ecmascript/quickjs/implementation.cpp deleted file mode 100644 index 5bc3b8c9..00000000 --- a/src/ecmascript/quickjs/implementation.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* The QuickJS domimplementation object. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#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" - -#include -#include - -#ifndef CONFIG_LIBDOM - -#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, ""); - - // 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(std::nothrow) xmlpp::Document(doc); - 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); -} -#endif diff --git a/src/ecmascript/quickjs/input.cpp b/src/ecmascript/quickjs/input.cpp deleted file mode 100644 index e1c79f14..00000000 --- a/src/ecmascript/quickjs/input.cpp +++ /dev/null @@ -1,1639 +0,0 @@ -/* The QuickJS input objects implementation. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "elinks.h" - -#include "bfu/dialog.h" -#include "cache/cache.h" -#include "cookies/cookies.h" -#include "dialogs/menu.h" -#include "dialogs/status.h" -#include "document/html/frames.h" -#include "document/document.h" -#include "document/forms.h" -#include "document/view.h" -#include "ecmascript/ecmascript.h" -#include "ecmascript/quickjs.h" -#include "ecmascript/quickjs/document.h" -#include "ecmascript/quickjs/form.h" -#include "ecmascript/quickjs/forms.h" -#include "ecmascript/quickjs/input.h" -#include "ecmascript/quickjs/window.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/memory.h" -#include "util/string.h" -#include "viewer/text/draw.h" -#include "viewer/text/form.h" -#include "viewer/text/link.h" -#include "viewer/text/vs.h" - -#include -#include - -#ifndef CONFIG_LIBDOM - -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -static JSClassID js_input_class_id; -static std::map map_inputs; - -JSValue getInput(JSContext *ctx, struct form_state *fs); - - -/* Accordingly to the JS specs, each input type should own object. That'd be a - * huge PITA though, however DOM comes to the rescue and defines just a single - * HTMLInputElement. The difference could be spotted only by some clever tricky - * JS code, but I hope it doesn't matter anywhere. --pasky */ - -static struct form_state *js_input_get_form_state(JSContext *ctx, JSValueConst jsinput); - -struct JSString { - uint32_t header; /* must come first, 32-bit */ - uint32_t len : 31; - uint8_t is_wide_char : 1; /* 0 = 8 bits, 1 = 16 bits characters */ - /* for JS_ATOM_TYPE_SYMBOL: hash = 0, atom_type = 3, - for JS_ATOM_TYPE_PRIVATE: hash = 1, atom_type = 3 - XXX: could change encoding to have one more bit in hash */ - uint32_t hash : 30; - uint8_t atom_type : 2; /* != 0 if atom, JS_ATOM_TYPE_x */ - uint32_t hash_next; /* atom_index for JS_ATOM_TYPE_SYMBOL */ -#ifdef DUMP_LEAKS - struct list_head link; /* string list */ -#endif - union { - uint8_t str8[0]; /* 8 bit strings will get an extra null terminator */ - uint16_t str16[0]; - } u; -}; - -typedef struct JSString JSString; - -static JSValue -unicode_to_value(JSContext *ctx, unicode_val_T u) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - JSValue str = JS_NewStringLen(ctx, " ", 8); - REF_JS(str); - - JSString *p = JS_VALUE_GET_STRING(str); - p->is_wide_char = 1; - - if (u <= 0xFFFF && !is_utf16_surrogate(u)) { - p->u.str16[0] = u; - p->len = 1; - return str; - } else if (needs_utf16_surrogates(u)) { - p->u.str16[0] = get_utf16_high_surrogate(u); - p->u.str16[1] = get_utf16_low_surrogate(u); - p->len = 2; - return str; - } else { - p->len = 1; - p->u.str16[0] = 0; - return str; - } -} - -static int -string_get(const JSString *p, int idx) -{ - return p->is_wide_char ? p->u.str16[idx] : p->u.str8[idx]; -} - -/* Convert the string *@vp to an access key. Return 0 for no access - * key, UCS_NO_CHAR on error, or the access key otherwise. */ -static unicode_val_T -js_value_to_accesskey(JSValueConst val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(val); - - JSString *p = JS_VALUE_GET_STRING(val); - - size_t len; - char16_t chr[2]; - - len = p->len; - - /* This implementation ignores extra characters in the string. */ - if (len < 1) - return 0; /* which means no access key */ - chr[0] = string_get(p, 0); - - if (!is_utf16_surrogate(chr[0])) { - return chr[0]; - } - if (len >= 2) { - chr[1] = string_get(p, 1); - if (is_utf16_high_surrogate(chr[0]) - && is_utf16_low_surrogate(chr[1])) { - return join_utf16_surrogates(chr[0], chr[1]); - } - } - return UCS_NO_CHAR; /* which the caller will reject */ -} - -static JSValue -js_input_get_property_accessKey(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - int linknum; - struct link *link = NULL; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - - linknum = get_form_control_link(document, fc); - /* Hiddens have no link. */ - if (linknum >= 0) link = &document->links[linknum]; - - if (!link) { - return JS_UNDEFINED; - } - - if (!link->accesskey) { - JSValue r = JS_NewStringLen(ctx, "", 0); - RETURN_JS(r); - } else { - JSValue vv = unicode_to_value(ctx, link->accesskey); - RETURN_JS(vv); - } - return JS_UNDEFINED; -} - -static JSValue -js_input_set_property_accessKey(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - int linknum; - struct link *link = NULL; - unicode_val_T accesskey; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - - linknum = get_form_control_link(document, fc); - /* Hiddens have no link. */ - if (linknum >= 0) link = &document->links[linknum]; - - if (!JS_IsString(val)) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - accesskey = js_value_to_accesskey(val); - - if (link) { - link->accesskey = accesskey; - } - - return JS_UNDEFINED; -} - -static JSValue -js_input_get_property_alt(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - - JSValue r = JS_NewString(ctx, fc->alt); - RETURN_JS(r); -} - -static JSValue -js_input_set_property_alt(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - const char *str; - char *string; - size_t len; - str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - string = stracpy(str); - JS_FreeCString(ctx, str); - mem_free_set(&fc->alt, string); - - return JS_UNDEFINED; -} - -static JSValue -js_input_get_property_checked(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct form_state *fs; - fs = js_input_get_form_state(ctx, this_val); - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - - return JS_NewBool(ctx, fs->state); -} - -static JSValue -js_input_set_property_checked(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - - if (fc->type != FC_CHECKBOX && fc->type != FC_RADIO) { - return JS_UNDEFINED; - } - fs->state = JS_ToBool(ctx, val); - - return JS_UNDEFINED; -} - -static JSValue -js_input_get_property_defaultChecked(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - - return JS_NewBool(ctx, fc->default_state); -} - -static JSValue -js_input_get_property_defaultValue(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - - if (!fs) { - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - - /* FIXME (bug 805): convert from the charset of the document */ - JSValue r = JS_NewString(ctx, fc->default_value); - RETURN_JS(r); -} - -static JSValue -js_input_get_property_disabled(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - - /* FIXME: --pasky */ - return JS_NewBool(ctx, fc->mode == FORM_MODE_DISABLED); -} - -static JSValue -js_input_set_property_disabled(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - - /* FIXME: --pasky */ - fc->mode = (JS_ToBool(ctx, val) ? FORM_MODE_DISABLED - : fc->mode == FORM_MODE_READONLY ? FORM_MODE_READONLY - : FORM_MODE_NORMAL); - - return JS_UNDEFINED; -} - -static JSValue -js_input_get_property_form(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - -#if 0 - JS::CallArgs args = CallArgsFromVp(argc, vp); - JS::RootedObject hobj(ctx, &args.thisv().toObject()); - - JS::RootedObject parent_form(ctx, JS::GetNonCCWObjectGlobal(hobj)); - assert(JS_InstanceOf(ctx, parent_form, &form_class, NULL)); - if_assert_failed { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return false; - } - - args.rval().setObject(*parent_form); -#endif - // TODO - return JS_UNDEFINED; -} - -static JSValue -js_input_get_property_maxLength(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - - return JS_NewInt32(ctx, fc->maxlength); -} - -static JSValue -js_input_set_property_maxLength(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - - JS_ToInt32(ctx, &fc->maxlength, val); - - return JS_UNDEFINED; -} - -static JSValue -js_input_get_property_name(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - - JSValue r = JS_NewString(ctx, fc->name); - RETURN_JS(r); -} - -/* @input_class.setProperty */ -static JSValue -js_input_set_property_name(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - - if (!fs) { - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - - const char *str; - char *string; - size_t len; - str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - - string = stracpy(str); - JS_FreeCString(ctx, str); - mem_free_set(&fc->name, string); - - return JS_UNDEFINED; -} - -static JSValue -js_input_get_property_readonly(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - - /* FIXME: --pasky */ - return JS_NewBool(ctx, fc->mode == FORM_MODE_READONLY); -} - -/* @input_class.setProperty */ -static JSValue -js_input_set_property_readonly(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - - /* FIXME: --pasky */ - fc->mode = (JS_ToBool(ctx, val) ? FORM_MODE_READONLY - : fc->mode == FORM_MODE_DISABLED ? FORM_MODE_DISABLED - : FORM_MODE_NORMAL); - - return JS_UNDEFINED; -} - -static JSValue -js_input_get_property_selectedIndex(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - - if (fc->type == FC_SELECT) { - return JS_NewInt32(ctx, fs->state); - } else { - return JS_UNDEFINED; - } -} - -/* @input_class.setProperty */ -static JSValue -js_input_set_property_selectedIndex(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - - if (fc->type == FC_SELECT) { - int item; - - JS_ToInt32(ctx, &item, val); - - if (item >= 0 && item < fc->nvalues) { - fs->state = item; - mem_free_set(&fs->value, stracpy(fc->values[item])); - } - } - - return JS_UNDEFINED; -} - -static JSValue -js_input_get_property_size(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - - return JS_NewInt32(ctx, fc->size); -} - -static JSValue -js_input_get_property_src(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - int linknum; - struct link *link = NULL; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - linknum = get_form_control_link(document, fc); - /* Hiddens have no link. */ - if (linknum >= 0) link = &document->links[linknum]; - - if (link && link->where_img) { - JSValue r = JS_NewString(ctx, link->where_img); - RETURN_JS(r); - } else { - return JS_UNDEFINED; - } -} - -static JSValue -js_input_set_property_src(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - int linknum; - struct link *link = NULL; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { - return JS_UNDEFINED; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - - linknum = get_form_control_link(document, fc); - /* Hiddens have no link. */ - if (linknum >= 0) link = &document->links[linknum]; - - if (link) { - const char *str; - char *string; - size_t len; - str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - - string = stracpy(str); - JS_FreeCString(ctx, str); - - mem_free_set(&link->where_img, string); - } - - return JS_UNDEFINED; -} - -static JSValue -js_input_get_property_tabIndex(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - int linknum; - struct link *link = NULL; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - - linknum = get_form_control_link(document, fc); - /* Hiddens have no link. */ - if (linknum >= 0) link = &document->links[linknum]; - - if (link) { - /* FIXME: This is WRONG. --pasky */ - return JS_NewInt32(ctx, link->number); - } else { - return JS_UNDEFINED; - } -} - -static JSValue -js_input_get_property_type(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - const char *s = NULL; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - - switch (fc->type) { - case FC_TEXT: s = "text"; break; - case FC_PASSWORD: s = "password"; break; - case FC_FILE: s = "file"; break; - case FC_CHECKBOX: s = "checkbox"; break; - case FC_RADIO: s = "radio"; break; - case FC_SUBMIT: s = "submit"; break; - case FC_IMAGE: s = "image"; break; - case FC_RESET: s = "reset"; break; - case FC_BUTTON: s = "button"; break; - case FC_HIDDEN: s = "hidden"; break; - case FC_SELECT: s = "select"; break; - default: INTERNAL("input_get_property() upon a non-input item."); break; - } - - JSValue r = JS_NewString(ctx, s); - RETURN_JS(r); -} - -static JSValue -js_input_get_property_value(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct form_state *fs; - fs = js_input_get_form_state(ctx, this_val); - - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - - JSValue r = JS_NewString(ctx, fs->value); - RETURN_JS(r); -} - -static JSValue -js_input_set_property_value(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct form_state *fs; - struct el_form_control *fc; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; - } - doc_view = vs->doc_view; - document = doc_view->document; - fs = js_input_get_form_state(ctx, this_val); - - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - fc = find_form_control(document, fs); - - assert(fc); - assert(fc->form && fs); - - if (fc->type != FC_FILE) { - const char *str; - char *string; - size_t len; - - str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - - string = stracpy(str); - JS_FreeCString(ctx, str); - - mem_free_set(&fs->value, string); - if (fc->type == FC_TEXT || fc->type == FC_PASSWORD) - fs->state = strlen(fs->value); - } - - return JS_UNDEFINED; -} - - -static struct form_state * -js_input_get_form_state(JSContext *ctx, JSValueConst jsinput) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(jsinput); - - struct form_state *fs = (struct form_state *)JS_GetOpaque(jsinput, js_input_class_id); - - return fs; -} - -/* @input_funcs{"blur"} */ -static JSValue -js_input_blur(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - /* We are a text-mode browser and there *always* has to be something - * selected. So we do nothing for now. (That was easy.) */ - return JS_UNDEFINED; -} - -/* @input_funcs{"click"} */ -static JSValue -js_input_click(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct session *ses; - struct form_state *fs; - struct el_form_control *fc; - int linknum; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - doc_view = vs->doc_view; - document = doc_view->document; - ses = doc_view->session; - fs = js_input_get_form_state(ctx, this_val); - - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - - assert(fs); - fc = find_form_control(document, fs); - assert(fc); - - linknum = get_form_control_link(document, fc); - /* Hiddens have no link. */ - if (linknum < 0) { - return JS_UNDEFINED; - } - - /* Restore old current_link afterwards? */ - jump_to_link_number(ses, doc_view, linknum); - if (enter(ses, doc_view, 0) == FRAME_EVENT_REFRESH) { - refresh_view(ses, doc_view, 0); - } else { - print_screen_status(ses); - } - - return JS_FALSE; -} - -/* @input_funcs{"focus"} */ -static JSValue -js_input_focus(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct document *document; - struct session *ses; - struct form_state *fs; - struct el_form_control *fc; - int linknum; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - doc_view = vs->doc_view; - document = doc_view->document; - ses = doc_view->session; - fs = js_input_get_form_state(ctx, this_val); - - if (!fs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_NULL; /* detached */ - } - - assert(fs); - fc = find_form_control(document, fs); - assert(fc); - - linknum = get_form_control_link(document, fc); - /* Hiddens have no link. */ - if (linknum < 0) { - return JS_UNDEFINED; - } - - jump_to_link_number(ses, doc_view, linknum); - - return JS_FALSE; -} - -/* @input_funcs{"select"} */ -static JSValue -js_input_select(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - /* We support no text selecting yet. So we do nothing for now. - * (That was easy, too.) */ - return JS_UNDEFINED; -} - -JSValue -js_get_input_object(JSContext *ctx, struct form_state *fs) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - return getInput(ctx, fs); -} - -static JSValue -js_input_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, "[input object]"); -} - - -static const JSCFunctionListEntry js_input_proto_funcs[] = { - JS_CGETSET_DEF("accessKey", js_input_get_property_accessKey, js_input_set_property_accessKey), - JS_CGETSET_DEF("alt", js_input_get_property_alt, js_input_set_property_alt), - JS_CGETSET_DEF("checked", js_input_get_property_checked, js_input_set_property_checked), - JS_CGETSET_DEF("defaultChecked", js_input_get_property_defaultChecked, nullptr), - JS_CGETSET_DEF("defaultValue",js_input_get_property_defaultValue, nullptr), - JS_CGETSET_DEF("disabled", js_input_get_property_disabled, js_input_set_property_disabled), - JS_CGETSET_DEF("form", js_input_get_property_form, nullptr), - JS_CGETSET_DEF("maxLength", js_input_get_property_maxLength, js_input_set_property_maxLength), - JS_CGETSET_DEF("name", js_input_get_property_name, js_input_set_property_name), - JS_CGETSET_DEF("readonly", js_input_get_property_readonly, js_input_set_property_readonly), - JS_CGETSET_DEF("selectedIndex", js_input_get_property_selectedIndex, js_input_set_property_selectedIndex), - JS_CGETSET_DEF("size", js_input_get_property_size, nullptr), - JS_CGETSET_DEF("src", js_input_get_property_src, js_input_set_property_src), - JS_CGETSET_DEF("tabindex", js_input_get_property_tabIndex, nullptr), - JS_CGETSET_DEF("type", js_input_get_property_type, nullptr), - JS_CGETSET_DEF("value", js_input_get_property_value, js_input_set_property_value), - JS_CFUNC_DEF("blur", 0 , js_input_blur), - JS_CFUNC_DEF("click", 0 , js_input_click), - JS_CFUNC_DEF("focus", 0 , js_input_focus), - JS_CFUNC_DEF("select", 0 , js_input_select), - JS_CFUNC_DEF("toString", 0, js_input_toString) -}; - -void -quickjs_detach_form_state(struct form_state *fs) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - JSValue jsinput = fs->ecmascript_obj; - - if (!JS_IsNull(jsinput)) { - map_inputs.erase(fs); - JS_SetOpaque(jsinput, nullptr); - fs->ecmascript_obj = JS_NULL; - } -} - -void -quickjs_moved_form_state(struct form_state *fs) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - JSValue jsinput = fs->ecmascript_obj; - REF_JS(jsinput); - - if (!JS_IsNull(jsinput)) { - map_inputs.erase(fs); - JS_SetOpaque(jsinput, fs); - map_inputs[fs] = jsinput; - } -} - -static -void js_input_finalizer(JSRuntime *rt, JSValue val) -{ - REF_JS(val); - - struct form_state *fs = (struct form_state *)JS_GetOpaque(val, js_input_class_id); - - if (fs) { - fs->ecmascript_obj = JS_NULL; - map_inputs.erase(fs); - } -} - - -static JSClassDef js_input_class = { - "input", - js_input_finalizer -}; - -static JSValue -js_input_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_input_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_input_init(JSContext *ctx, JSValue global_obj) -{ - REF_JS(global_obj); - - JSValue input_proto, input_class; - - /* create the input class */ - JS_NewClassID(&js_input_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_input_class_id, &js_input_class); - - input_proto = JS_NewObject(ctx); - REF_JS(input_proto); - - JS_SetPropertyFunctionList(ctx, input_proto, js_input_proto_funcs, countof(js_input_proto_funcs)); - - input_class = JS_NewCFunction2(ctx, js_input_ctor, "input", 0, JS_CFUNC_constructor, 0); - REF_JS(input_class); - - /* set proto.constructor and ctor.prototype */ - JS_SetConstructor(ctx, input_class, input_proto); - JS_SetClassProto(ctx, js_input_class_id, input_proto); - - JS_SetPropertyStr(ctx, global_obj, "input", JS_DupValue(ctx, input_proto)); - return 0; -} - -JSValue -getInput(JSContext *ctx, struct form_state *fs) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - static int initialized; - if (!initialized) { - JS_NewClassID(&js_input_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_input_class_id, &js_input_class); - initialized = 1; - map_inputs.clear(); - } - auto node_find = map_inputs.find(fs); - - if (node_find != map_inputs.end()) { - JSValue r = JS_DupValue(ctx, node_find->second); - RETURN_JS(r); - } - JSValue input_obj = JS_NewObjectClass(ctx, js_input_class_id); - - JS_SetPropertyFunctionList(ctx, input_obj, js_input_proto_funcs, countof(js_input_proto_funcs)); - JS_SetClassProto(ctx, js_input_class_id, input_obj); - JS_SetOpaque(input_obj, fs); - fs->ecmascript_obj = input_obj; - map_inputs[fs] = input_obj; - - JSValue rr = JS_DupValue(ctx, input_obj); - RETURN_JS(rr); -} -#endif diff --git a/src/ecmascript/quickjs/keyboard.cpp b/src/ecmascript/quickjs/keyboard.cpp deleted file mode 100644 index 1a4134ce..00000000 --- a/src/ecmascript/quickjs/keyboard.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/* The QuickJS KeyboardEvent object implementation. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "elinks.h" - -#include "bfu/dialog.h" -#include "cache/cache.h" -#include "cookies/cookies.h" -#include "dialogs/menu.h" -#include "dialogs/status.h" -#include "document/html/frames.h" -#include "document/document.h" -#include "document/forms.h" -#include "document/view.h" -#include "ecmascript/ecmascript.h" -#include "ecmascript/quickjs.h" -#include "ecmascript/quickjs/heartbeat.h" -#include "ecmascript/quickjs/keyboard.h" -#include "ecmascript/timer.h" -#include "intl/libintl.h" -#include "main/select.h" -#include "main/timer.h" -#include "network/connection.h" -#include "osdep/newwin.h" -#include "osdep/sysname.h" -#include "protocol/http/http.h" -#include "protocol/uri.h" -#include "session/download.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/memory.h" -#include "util/string.h" -#include "viewer/text/draw.h" -#include "viewer/text/form.h" -#include "viewer/text/link.h" -#include "viewer/text/vs.h" - -#include -#include -#include -#include -#include -#include - -#ifndef CONFIG_LIBDOM - -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -static JSClassID js_keyboardEvent_class_id; - -static JSValue js_keyboardEvent_get_property_key(JSContext *ctx, JSValueConst this_val); -static JSValue js_keyboardEvent_get_property_keyCode(JSContext *ctx, JSValueConst this_val); - -static unicode_val_T keyCode; - -struct keyboard { - unicode_val_T keyCode; -}; - -static -void js_keyboardEvent_finalizer(JSRuntime *rt, JSValue val) -{ - REF_JS(val); - - struct keyboard *keyb = (struct keyboard *)JS_GetOpaque(val, js_keyboardEvent_class_id); - - if (keyb) { - mem_free(keyb); - } -} - -static JSClassDef js_keyboardEvent_class = { - "KeyboardEvent", - js_keyboardEvent_finalizer -}; - -#if 0 -static JSValue -js_keyboardEvent_ctor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv) -{ - REF_JS(new_target); - - JSValue obj = JS_UNDEFINED; - JSValue proto; - - struct keyboard *keyb = (struct keyboard *)mem_calloc(1, sizeof(*keyb)); - - if (!keyb) { - return JS_EXCEPTION; - } - - /* 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_keyboardEvent_class_id); - JS_FreeValue(ctx, proto); - - if (JS_IsException(obj)) { - goto fail; - } - keyb->keyCode = keyCode; - JS_SetOpaque(obj, keyb); - - RETURN_JS(obj); - -fail: - JS_FreeValue(ctx, obj); - mem_free(keyb); - return JS_EXCEPTION; -} -#endif - -static const JSCFunctionListEntry js_keyboardEvent_proto_funcs[] = { - JS_CGETSET_DEF("key", js_keyboardEvent_get_property_key, nullptr), - JS_CGETSET_DEF("keyCode", js_keyboardEvent_get_property_keyCode, nullptr) -}; - -static JSValue -js_keyboardEvent_get_property_key(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct keyboard *keyb = static_cast(JS_GetOpaque(this_val, js_keyboardEvent_class_id)); - - if (!keyb) { - return JS_NULL; - } - char text[8] = {0}; - - *text = keyb->keyCode; - JSValue r = JS_NewString(ctx, text); - - RETURN_JS(r); -} - -static JSValue -js_keyboardEvent_get_property_keyCode(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct keyboard *keyb = static_cast(JS_GetOpaque(this_val, js_keyboardEvent_class_id)); - - if (!keyb) { - return JS_NULL; - } - return JS_NewUint32(ctx, keyb->keyCode); -} - -JSValue -get_keyboardEvent(JSContext *ctx, struct term_event *ev) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - static int initialized; - /* create the element class */ - if (!initialized) { - JS_NewClassID(&js_keyboardEvent_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_keyboardEvent_class_id, &js_keyboardEvent_class); - initialized = 1; - } - struct keyboard *keyb = (struct keyboard *)mem_calloc(1, sizeof(*keyb)); - - if (!keyb) { - return JS_NULL; - } - keyCode = keyb->keyCode = get_kbd_key(ev); - JSValue keyb_obj = JS_NewObjectClass(ctx, js_keyboardEvent_class_id); - JS_SetPropertyFunctionList(ctx, keyb_obj, js_keyboardEvent_proto_funcs, countof(js_keyboardEvent_proto_funcs)); - JS_SetClassProto(ctx, js_keyboardEvent_class_id, keyb_obj); - JS_SetOpaque(keyb_obj, keyb); - - JSValue rr = JS_DupValue(ctx, keyb_obj); - RETURN_JS(rr); -} -#endif diff --git a/src/ecmascript/quickjs/localstorage.cpp b/src/ecmascript/quickjs/localstorage.cpp deleted file mode 100644 index 2a72d372..00000000 --- a/src/ecmascript/quickjs/localstorage.cpp +++ /dev/null @@ -1,269 +0,0 @@ -/* The quickjs localstorage object implementation. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "elinks.h" - -#include "bfu/dialog.h" -#include "cache/cache.h" -#include "config/home.h" -#include "cookies/cookies.h" -#include "dialogs/menu.h" -#include "dialogs/status.h" -#include "document/html/frames.h" -#include "document/document.h" -#include "document/forms.h" -#include "document/view.h" -#include "ecmascript/ecmascript.h" -#include "ecmascript/localstorage-db.h" -#include "ecmascript/quickjs.h" -#include "ecmascript/quickjs/localstorage.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/memory.h" -#include "util/string.h" -#include "viewer/text/draw.h" -#include "viewer/text/form.h" -#include "viewer/text/link.h" -#include "viewer/text/vs.h" - -#include -#include "document/renderer.h" -#include "document/refresh.h" -#include "terminal/screen.h" - -#ifndef CONFIG_LIBDOM - -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -static JSClassID js_localstorage_class_id; - -/* IMPLEMENTS READ FROM STORAGE USING SQLITE DATABASE */ -static char * -readFromStorage(const char *key) -{ - char *val; - - if (local_storage_ready==0) - { - db_prepare_structure(local_storage_filename); - local_storage_ready=1; - } - - val = db_query_by_key(local_storage_filename, key); - - //DBG("Read: %s %s %s",local_storage_filename, key, val); - - return val; -} - -static void -removeFromStorage(const char *key) -{ - if (local_storage_ready==0) - { - db_prepare_structure(local_storage_filename); - local_storage_ready=1; - } - db_delete_from(local_storage_filename, key); -} - -/* IMPLEMENTS SAVE TO STORAGE USING SQLITE DATABASE */ -static void -saveToStorage(const char *key, const char *val) -{ - if (local_storage_ready==0) { - db_prepare_structure(local_storage_filename); - local_storage_ready=1; - } - - int rows_affected=0; - - rows_affected=db_update_set(local_storage_filename, key, val); - - if (rows_affected==0) { - rows_affected=db_insert_into(local_storage_filename, key, val); - } - - // DBG(log, "UPD ROWS: %d KEY: %s VAL: %s",rows_affected,key,val); - -} - -static JSValue -js_localstorage_getitem(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) - { - return JS_UNDEFINED; - } - - const char *key; - size_t len; - - key = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!key) { - return JS_EXCEPTION; - } - - char *val = readFromStorage(key); - JS_FreeCString(ctx, key); - - if (!val) { - return JS_NULL; - } - - JSValue ret = JS_NewString(ctx, val); - mem_free(val); - RETURN_JS(ret); -} - -static JSValue -js_localstorage_removeitem(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) - { - return JS_UNDEFINED; - } - - const char *key; - size_t len; - - key = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!key) { - return JS_EXCEPTION; - } - - removeFromStorage(key); - JS_FreeCString(ctx, key); - - return JS_UNDEFINED; -} - -/* @localstorage_funcs{"setItem"} */ -static JSValue -js_localstorage_setitem(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#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); - - if (argc != 2) - { - return JS_UNDEFINED; - } - - const char *key_str, *val_str; - size_t len_key, len_val; - - key_str = JS_ToCStringLen(ctx, &len_key, argv[0]); - - if (!key_str) { - return JS_EXCEPTION; - } - - val_str = JS_ToCStringLen(ctx, &len_val, argv[1]); - - if (!val_str) { - JS_FreeCString(ctx, key_str); - return JS_EXCEPTION; - } - - saveToStorage(key_str, val_str); - JS_FreeCString(ctx, key_str); - JS_FreeCString(ctx, val_str); - -#ifdef CONFIG_LEDS - set_led_value(interpreter->vs->doc_view->session->status.ecmascript_led, 'J'); -#endif - return JS_TRUE; -} - -static JSValue -js_localstorage_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, "[localstorage object]"); -} - -static const JSCFunctionListEntry js_localstorage_proto_funcs[] = { - JS_CFUNC_DEF("getItem", 1, js_localstorage_getitem), - JS_CFUNC_DEF("removeItem", 1, js_localstorage_removeitem), - JS_CFUNC_DEF("setItem", 2, js_localstorage_setitem), - JS_CFUNC_DEF("toString", 0, js_localstorage_toString) -}; - -static JSClassDef js_localstorage_class = { - "localStorage", -}; - -int -js_localstorage_init(JSContext *ctx) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - static int initialized; - - if (!initialized) { - /* create the localstorage class */ - JS_NewClassID(&js_localstorage_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_localstorage_class_id, &js_localstorage_class); - initialized = 1; - } - - JSValue global_obj = JS_GetGlobalObject(ctx); - REF_JS(global_obj); - - JSValue localstorage_obj = JS_NewObjectClass(ctx, js_localstorage_class_id); - REF_JS(localstorage_obj); - - JS_SetPropertyFunctionList(ctx, localstorage_obj, js_localstorage_proto_funcs, countof(js_localstorage_proto_funcs)); - REF_JS(localstorage_obj); - - JS_SetClassProto(ctx, js_localstorage_class_id, localstorage_obj); - REF_JS(localstorage_obj); - - JS_SetPropertyStr(ctx, global_obj, "localStorage", JS_DupValue(ctx, localstorage_obj)); - REF_JS(localstorage_obj); - - JS_FreeValue(ctx, global_obj); - - return 0; -} -#endif diff --git a/src/ecmascript/quickjs/location.cpp b/src/ecmascript/quickjs/location.cpp deleted file mode 100644 index b727f5bf..00000000 --- a/src/ecmascript/quickjs/location.cpp +++ /dev/null @@ -1,679 +0,0 @@ -/* The QuickJS location object implementation. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "elinks.h" - -#include "bfu/dialog.h" -#include "cache/cache.h" -#include "cookies/cookies.h" -#include "dialogs/menu.h" -#include "dialogs/status.h" -#include "document/html/frames.h" -#include "document/document.h" -#include "document/forms.h" -#include "document/view.h" -#include "ecmascript/ecmascript.h" -#include "ecmascript/quickjs.h" -#include "ecmascript/quickjs/location.h" -#include "ecmascript/quickjs/window.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/memory.h" -#include "util/string.h" -#include "viewer/text/draw.h" -#include "viewer/text/form.h" -#include "viewer/text/link.h" -#include "viewer/text/vs.h" - -#ifndef CONFIG_LIBDOM - -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -static JSClassID js_location_class_id; - -static JSValue -js_location_get_property_hash(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; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - - struct string fragment; - if (!init_string(&fragment)) { - return JS_EXCEPTION; - } - - if (vs->uri->fragmentlen) { - add_bytes_to_string(&fragment, vs->uri->fragment, vs->uri->fragmentlen); - } - - JSValue ret = JS_NewStringLen(ctx, fragment.source, fragment.length); - done_string(&fragment); - - RETURN_JS(ret); -} - -static JSValue -js_location_get_property_host(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; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - - char *str = get_uri_string(vs->uri, URI_HOST_PORT); - - if (!str) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - - JSValue ret = JS_NewString(ctx, str); - mem_free(str); - - RETURN_JS(ret); -} - -static JSValue -js_location_get_property_hostname(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; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - - char *str = get_uri_string(vs->uri, URI_HOST); - - if (!str) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - - JSValue ret = JS_NewString(ctx, str); - mem_free(str); - - RETURN_JS(ret); -} - -static JSValue -js_location_get_property_href(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; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - - char *str = get_uri_string(vs->uri, URI_ORIGINAL); - - if (!str) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - - JSValue ret = JS_NewString(ctx, str); - mem_free(str); - - RETURN_JS(ret); -} - -static JSValue -js_location_get_property_origin(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; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - - char *str = get_uri_string(vs->uri, URI_SERVER); - - if (!str) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - - JSValue ret = JS_NewString(ctx, str); - mem_free(str); - - RETURN_JS(ret); -} - -static JSValue -js_location_get_property_pathname(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; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - - struct string pathname; - if (!init_string(&pathname)) { - return JS_EXCEPTION; - } - - const char *query = (const char *)memchr(vs->uri->data, '?', vs->uri->datalen); - int len = (query ? query - vs->uri->data : vs->uri->datalen); - - add_bytes_to_string(&pathname, vs->uri->data, len); - - JSValue ret = JS_NewStringLen(ctx, pathname.source, pathname.length); - done_string(&pathname); - - RETURN_JS(ret); -} - -static JSValue -js_location_get_property_port(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; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - - struct string port; - if (!init_string(&port)) { - return JS_EXCEPTION; - } - if (vs->uri->portlen) { - add_bytes_to_string(&port, vs->uri->port, vs->uri->portlen); - } - - JSValue ret = JS_NewStringLen(ctx, port.source, port.length); - done_string(&port); - - RETURN_JS(ret); -} - -static JSValue -js_location_get_property_protocol(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; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - - struct string proto; - if (!init_string(&proto)) { - return JS_EXCEPTION; - } - - /* Custom or unknown keep the URI untouched. */ - if (vs->uri->protocol == PROTOCOL_UNKNOWN) { - add_to_string(&proto, struri(vs->uri)); - } else { - add_bytes_to_string(&proto, vs->uri->string, vs->uri->protocollen); - add_char_to_string(&proto, ':'); - } - - JSValue ret = JS_NewStringLen(ctx, proto.source, proto.length); - done_string(&proto); - - RETURN_JS(ret); -} - -static JSValue -js_location_get_property_search(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; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - - struct string search; - if (!init_string(&search)) { - return JS_EXCEPTION; - } - - const char *query = (const char *)memchr(vs->uri->data, '?', vs->uri->datalen); - - if (query) { - add_bytes_to_string(&search, query, strcspn(query, "#" POST_CHAR_S)); - } - - JSValue ret = JS_NewStringLen(ctx, search.source, search.length); - done_string(&search); - - RETURN_JS(ret); -} - -static JSValue -js_location_set_property_hash(JSContext *ctx, JSValueConst this_val, JSValue 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; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - - size_t len; - - const char *str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - location_goto_const(vs->doc_view, str); - JS_FreeCString(ctx, str); - - return JS_UNDEFINED; -} - -static JSValue -js_location_set_property_host(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - struct view_state *vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - size_t len; - - const char *str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - location_goto_const(vs->doc_view, str); - JS_FreeCString(ctx, str); - - return JS_UNDEFINED; -} - -static JSValue -js_location_set_property_hostname(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - struct view_state *vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - size_t len; - - const char *str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - location_goto_const(vs->doc_view, str); - JS_FreeCString(ctx, str); - - return JS_UNDEFINED; -} - -static JSValue -js_location_set_property_href(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - struct view_state *vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - size_t len; - - const char *str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - location_goto_const(vs->doc_view, str); - JS_FreeCString(ctx, str); - - return JS_UNDEFINED; -} - -static JSValue -js_location_set_property_pathname(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - struct view_state *vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - size_t len; - - const char *str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - location_goto_const(vs->doc_view, str); - JS_FreeCString(ctx, str); - - return JS_UNDEFINED; -} - -static JSValue -js_location_set_property_port(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - struct view_state *vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - size_t len; - - const char *str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - location_goto_const(vs->doc_view, str); - JS_FreeCString(ctx, str); - - return JS_UNDEFINED; -} - -static JSValue -js_location_set_property_protocol(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - struct view_state *vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - size_t len; - - const char *str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - location_goto_const(vs->doc_view, str); - JS_FreeCString(ctx, str); - - return JS_UNDEFINED; -} - -static JSValue -js_location_set_property_search(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - struct view_state *vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - size_t len; - - const char *str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - location_goto_const(vs->doc_view, str); - JS_FreeCString(ctx, str); - - return JS_UNDEFINED; -} - -static JSValue -js_location_reload(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#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; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_EXCEPTION; - } - location_goto_const(vs->doc_view, ""); - - return JS_UNDEFINED; -} - -/* @location_funcs{"toString"}, @location_funcs{"toLocaleString"} */ -static JSValue -js_location_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_location_get_property_href(ctx, this_val); -} - -static const JSCFunctionListEntry js_location_proto_funcs[] = { - JS_CGETSET_DEF("hash", js_location_get_property_hash, js_location_set_property_hash), - JS_CGETSET_DEF("host", js_location_get_property_host, js_location_set_property_host), - JS_CGETSET_DEF("hostname", js_location_get_property_hostname, js_location_set_property_hostname), - JS_CGETSET_DEF("href", js_location_get_property_href, js_location_set_property_href), - JS_CGETSET_DEF("origin", js_location_get_property_origin, nullptr), - JS_CGETSET_DEF("pathname", js_location_get_property_pathname, js_location_set_property_pathname), - JS_CGETSET_DEF("port", js_location_get_property_port, js_location_set_property_port), - JS_CGETSET_DEF("protocol", js_location_get_property_protocol, js_location_set_property_protocol), - JS_CGETSET_DEF("search", js_location_get_property_search, js_location_set_property_search), - JS_CFUNC_DEF("reload", 0, js_location_reload), - JS_CFUNC_DEF("toString", 0, js_location_toString), - JS_CFUNC_DEF("toLocaleString", 0, js_location_toString), -}; - -static JSClassDef js_location_class = { - "location", -}; - -JSValue -js_location_init(JSContext *ctx) -{ - JSValue location_proto; - - /* create the location class */ - JS_NewClassID(&js_location_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_location_class_id, &js_location_class); - - JSValue global_obj = JS_GetGlobalObject(ctx); - REF_JS(global_obj); - - location_proto = JS_NewObject(ctx); - REF_JS(location_proto); - - JS_SetPropertyFunctionList(ctx, location_proto, js_location_proto_funcs, countof(js_location_proto_funcs)); - JS_SetClassProto(ctx, js_location_class_id, location_proto); - JS_SetPropertyStr(ctx, global_obj, "location", JS_DupValue(ctx, location_proto)); - - JS_FreeValue(ctx, global_obj); - - RETURN_JS(location_proto); -} -#endif diff --git a/src/ecmascript/quickjs/meson.build b/src/ecmascript/quickjs/meson.build deleted file mode 100644 index c82de35d..00000000 --- a/src/ecmascript/quickjs/meson.build +++ /dev/null @@ -1,2 +0,0 @@ -srcs += files('attr.cpp', 'attributes.cpp', 'collection.cpp', 'console.cpp', 'document.cpp', 'element.cpp', 'form.cpp', 'forms.cpp', 'heartbeat.cpp', 'history.cpp', 'implementation.cpp', -'input.cpp', 'keyboard.cpp', 'localstorage.cpp', 'location.cpp', 'message.cpp', 'navigator.cpp', 'nodelist.cpp', 'screen.cpp', 'unibar.cpp', 'window.cpp', 'xhr.cpp') diff --git a/src/ecmascript/quickjs/message.cpp b/src/ecmascript/quickjs/message.cpp deleted file mode 100644 index 6a3b758f..00000000 --- a/src/ecmascript/quickjs/message.cpp +++ /dev/null @@ -1,258 +0,0 @@ -/* The QuickJS MessageEvent object implementation. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "elinks.h" - -#include "bfu/dialog.h" -#include "cache/cache.h" -#include "cookies/cookies.h" -#include "dialogs/menu.h" -#include "dialogs/status.h" -#include "document/html/frames.h" -#include "document/document.h" -#include "document/forms.h" -#include "document/view.h" -#include "ecmascript/ecmascript.h" -#include "ecmascript/quickjs.h" -#include "ecmascript/quickjs/heartbeat.h" -#include "ecmascript/quickjs/message.h" -#include "ecmascript/timer.h" -#include "intl/libintl.h" -#include "main/select.h" -#include "main/timer.h" -#include "network/connection.h" -#include "osdep/newwin.h" -#include "osdep/sysname.h" -#include "protocol/http/http.h" -#include "protocol/uri.h" -#include "session/download.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/memory.h" -#include "util/string.h" -#include "viewer/text/draw.h" -#include "viewer/text/form.h" -#include "viewer/text/link.h" -#include "viewer/text/vs.h" - -#include -#include -#include -#include -#include -#include - -#ifndef CONFIG_LIBDOM - -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -static JSClassID js_messageEvent_class_id; - -static JSValue js_messageEvent_get_property_data(JSContext *cx, JSValueConst this_val); -static JSValue js_messageEvent_get_property_lastEventId(JSContext *cx, JSValueConst this_val); -static JSValue js_messageEvent_get_property_origin(JSContext *cx, JSValueConst this_val); -static JSValue js_messageEvent_get_property_source(JSContext *cx, JSValueConst this_val); - -struct message_event { - char *data; - char *lastEventId; - char *origin; - char *source; -}; - -static -void js_messageEvent_finalizer(JSRuntime *rt, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(val); - - struct message_event *event = (struct message_event *)JS_GetOpaque(val, js_messageEvent_class_id); - - if (event) { - mem_free_if(event->data); - mem_free_if(event->lastEventId); - mem_free_if(event->origin); - mem_free_if(event->source); - mem_free(event); - } -} - -static JSClassDef js_messageEvent_class = { - "MessageEvent", - js_messageEvent_finalizer -}; - -#if 0 -static JSValue -js_messageEvent_ctor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(new_target); - - JSValue obj = JS_UNDEFINED; - JSValue proto; - - struct message_event *event = (struct message_event *)mem_calloc(1, sizeof(*event)); - - if (!event) { - return JS_EXCEPTION; - } - - /* 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_messageEvent_class_id); - JS_FreeValue(ctx, proto); - - if (JS_IsException(obj)) { - goto fail; - } - JS_SetOpaque(obj, event); - - RETURN_JS(obj); - -fail: - JS_FreeValue(ctx, obj); - mem_free(event); - return JS_EXCEPTION; -} -#endif - -static const JSCFunctionListEntry js_messageEvent_proto_funcs[] = { - JS_CGETSET_DEF("data", js_messageEvent_get_property_data, nullptr), - JS_CGETSET_DEF("lastEventId", js_messageEvent_get_property_lastEventId, nullptr), - JS_CGETSET_DEF("origin", js_messageEvent_get_property_origin, nullptr), - JS_CGETSET_DEF("source", js_messageEvent_get_property_source, nullptr) -}; - -static JSValue -js_messageEvent_get_property_data(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct message_event *event = static_cast(JS_GetOpaque(this_val, js_messageEvent_class_id)); - - if (!event || !event->data) { - return JS_NULL; - } - JSValue r = JS_NewString(ctx, event->data); - - RETURN_JS(r); -} - -static JSValue -js_messageEvent_get_property_lastEventId(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct message_event *event = static_cast(JS_GetOpaque(this_val, js_messageEvent_class_id)); - - if (!event || !event->lastEventId) { - return JS_NULL; - } - JSValue r = JS_NewString(ctx, event->lastEventId); - - RETURN_JS(r); -} - -static JSValue -js_messageEvent_get_property_origin(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct message_event *event = static_cast(JS_GetOpaque(this_val, js_messageEvent_class_id)); - - if (!event || !event->origin) { - return JS_NULL; - } - JSValue r = JS_NewString(ctx, event->origin); - - RETURN_JS(r); -} - -static JSValue -js_messageEvent_get_property_source(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct message_event *event = static_cast(JS_GetOpaque(this_val, js_messageEvent_class_id)); - - if (!event || !event->source) { - return JS_NULL; - } - JSValue r = JS_NewString(ctx, event->source); - - RETURN_JS(r); -} - -static int lastEventId; - -JSValue -get_messageEvent(JSContext *ctx, char *data, char *origin, char *source) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - static int initialized; - /* create the element class */ - if (!initialized) { - JS_NewClassID(&js_messageEvent_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_messageEvent_class_id, &js_messageEvent_class); - initialized = 1; - } - struct message_event *event = (struct message_event *)mem_calloc(1, sizeof(*event)); - - if (!event) { - return JS_NULL; - } - event->data = null_or_stracpy(data); - event->origin = null_or_stracpy(origin); - event->source = null_or_stracpy(source); - - char id[32]; - - snprintf(id, 31, "%d", ++lastEventId); - event->lastEventId = stracpy(id); - - JSValue event_obj = JS_NewObjectClass(ctx, js_messageEvent_class_id); - JS_SetPropertyFunctionList(ctx, event_obj, js_messageEvent_proto_funcs, countof(js_messageEvent_proto_funcs)); - JS_SetClassProto(ctx, js_messageEvent_class_id, event_obj); - JS_SetOpaque(event_obj, event); - - JSValue rr = JS_DupValue(ctx, event_obj); - RETURN_JS(rr); -} -#endif diff --git a/src/ecmascript/quickjs/navigator.cpp b/src/ecmascript/quickjs/navigator.cpp deleted file mode 100644 index a901c4d7..00000000 --- a/src/ecmascript/quickjs/navigator.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* The Quickjs navigator object implementation. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "elinks.h" - -#include "bfu/dialog.h" -#include "cache/cache.h" -#include "cookies/cookies.h" -#include "dialogs/menu.h" -#include "dialogs/status.h" -#include "document/html/frames.h" -#include "document/document.h" -#include "document/forms.h" -#include "document/view.h" -#include "ecmascript/ecmascript.h" -#include "ecmascript/quickjs.h" -#include "ecmascript/quickjs/navigator.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/memory.h" -#include "util/string.h" -#include "viewer/text/draw.h" -#include "viewer/text/form.h" -#include "viewer/text/link.h" -#include "viewer/text/vs.h" - -#ifndef CONFIG_LIBDOM - -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -static JSClassID js_navigator_class_id; - -/* @navigator_class.getProperty */ - -static JSValue -js_navigator_get_property_appCodeName(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - JSValue r = JS_NewString(ctx, "Mozilla"); /* More like a constant nowadays. */ - RETURN_JS(r); -} - -static JSValue -js_navigator_get_property_appName(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - JSValue r = JS_NewString(ctx, "ELinks (roughly compatible with Netscape Navigator, Mozilla and Microsoft Internet Explorer)"); - RETURN_JS(r); -} - -static JSValue -js_navigator_get_property_appVersion(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - JSValue r = JS_NewString(ctx, VERSION); - RETURN_JS(r); -} - -static JSValue -js_navigator_get_property_language(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - -#ifdef CONFIG_NLS - if (get_opt_bool("protocol.http.accept_ui_language", NULL)) { - JSValue r = JS_NewString(ctx, language_to_iso639(current_language)); - RETURN_JS(r); - } -#endif - return JS_UNDEFINED; -} - -static JSValue -js_navigator_get_property_platform(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - JSValue r = JS_NewString(ctx, system_name); - RETURN_JS(r); -} - -static JSValue -js_navigator_get_property_userAgent(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - char *optstr = get_opt_str("protocol.http.user_agent", NULL); - - if (*optstr && strcmp(optstr, " ")) { - char *ustr, ts[64] = ""; - static char custr[256]; - /* TODO: Somehow get the terminal in which the - * document is actually being displayed. */ - struct terminal *term = get_default_terminal(); - - if (term) { - unsigned int tslen = 0; - - ulongcat(ts, &tslen, term->width, 3, 0); - ts[tslen++] = 'x'; - ulongcat(ts, &tslen, term->height, 3, 0); - } - ustr = subst_user_agent(optstr, VERSION_STRING, system_name, ts); - - if (ustr) { - safe_strncpy(custr, ustr, 256); - mem_free(ustr); - - JSValue r = JS_NewString(ctx, custr); - RETURN_JS(r); - } - } - JSValue rr = JS_NewString(ctx, system_name); - RETURN_JS(rr); -} - -static JSValue -js_navigator_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, "[navigator object]"); -} - -static const JSCFunctionListEntry js_navigator_proto_funcs[] = { - JS_CGETSET_DEF("appCodeName", js_navigator_get_property_appCodeName, nullptr), - JS_CGETSET_DEF("appName", js_navigator_get_property_appName, nullptr), - JS_CGETSET_DEF("appVersion", js_navigator_get_property_appVersion, nullptr), - JS_CGETSET_DEF("language", js_navigator_get_property_language, nullptr), - JS_CGETSET_DEF("platform", js_navigator_get_property_platform, nullptr), - JS_CGETSET_DEF("userAgent", js_navigator_get_property_userAgent, nullptr), - JS_CFUNC_DEF("toString", 0, js_navigator_toString) -}; - -static JSClassDef js_navigator_class = { - "navigator", -}; - -int -js_navigator_init(JSContext *ctx) -{ - JSValue navigator_proto; - - /* create the navigator class */ - JS_NewClassID(&js_navigator_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_navigator_class_id, &js_navigator_class); - - JSValue global_obj = JS_GetGlobalObject(ctx); - REF_JS(global_obj); - - navigator_proto = JS_NewObject(ctx); - REF_JS(navigator_proto); - - JS_SetPropertyFunctionList(ctx, navigator_proto, js_navigator_proto_funcs, countof(js_navigator_proto_funcs)); - JS_SetClassProto(ctx, js_navigator_class_id, navigator_proto); - JS_SetPropertyStr(ctx, global_obj, "navigator", JS_DupValue(ctx, navigator_proto)); - - JS_FreeValue(ctx, global_obj); - - return 0; -} -#endif diff --git a/src/ecmascript/quickjs/nodelist.cpp b/src/ecmascript/quickjs/nodelist.cpp deleted file mode 100644 index a1c6cee4..00000000 --- a/src/ecmascript/quickjs/nodelist.cpp +++ /dev/null @@ -1,238 +0,0 @@ -/* The QuickJS nodeList object implementation. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "elinks.h" - -#include "bfu/dialog.h" -#include "cache/cache.h" -#include "cookies/cookies.h" -#include "dialogs/menu.h" -#include "dialogs/status.h" -#include "document/html/frames.h" -#include "document/document.h" -#include "document/forms.h" -#include "document/view.h" -#include "ecmascript/ecmascript.h" -#include "ecmascript/quickjs.h" -#include "ecmascript/quickjs/element.h" -#include "ecmascript/quickjs/nodelist.h" -#include "ecmascript/quickjs/window.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/memory.h" -#include "util/string.h" -#include "viewer/text/draw.h" -#include "viewer/text/form.h" -#include "viewer/text/link.h" -#include "viewer/text/vs.h" - -#include -#include -#include -#include -#include - -#include -#include -#include - -#ifndef CONFIG_LIBDOM - -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -static std::map map_nodelist; -static std::map map_rev_nodelist; - -static void * -js_nodeList_GetOpaque(JSValueConst this_val) -{ - REF_JS(this_val); - - return map_rev_nodelist[this_val]; -} - -static void -js_nodeList_SetOpaque(JSValueConst this_val, void *node) -{ - REF_JS(this_val); - - if (!node) { - map_rev_nodelist.erase(this_val); - } else { - map_rev_nodelist[this_val] = node; - } -} - -#if 0 -static JSValue -js_nodeList_get_property_length(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - xmlpp::Node::NodeList *nl = static_cast(js_nodeList_GetOpaque(this_val)); - - if (!nl) { - return JS_NewInt32(ctx, 0); - } - - return JS_NewInt32(ctx, nl->size()); -} -#endif - -static JSValue -js_nodeList_item2(JSContext *ctx, JSValueConst this_val, int idx) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Node::NodeList *nl = static_cast(js_nodeList_GetOpaque(this_val)); - - if (!nl) { - return JS_UNDEFINED; - } - - xmlpp::Node *element = nullptr; - - auto it = nl->begin(); - auto end = nl->end(); - for (int i = 0; it != end; ++it, ++i) { - if (i == idx) { - element = *it; - break; - } - } - - if (!element) { - return JS_UNDEFINED; - } - - return getElement(ctx, element); -} - -static JSValue -js_nodeList_item(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) { - return JS_UNDEFINED; - } - - int index; - JS_ToInt32(ctx, &index, argv[0]); - - return js_nodeList_item2(ctx, this_val, index); -} - -static void -js_nodeList_set_items(JSContext *ctx, JSValue this_val, void *node) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - xmlpp::Node::NodeList *nl = static_cast(node); - - if (!nl) { - return; - } - - auto it = nl->begin(); - auto end = nl->end(); - for (int i = 0; it != end; ++it, ++i) { - xmlpp::Node *element = *it; - - if (element) { - JSValue obj = getElement(ctx, element); - REF_JS(obj); - - JS_SetPropertyUint32(ctx, this_val, i, JS_DupValue(ctx, obj)); - JS_FreeValue(ctx, obj); - } - } -} - -static JSValue -js_nodeList_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, "[nodeList object]"); -} - -static const JSCFunctionListEntry js_nodeList_proto_funcs[] = { -// JS_CGETSET_DEF("length", js_nodeList_get_property_length, nullptr), - JS_CFUNC_DEF("item", 1, js_nodeList_item), - JS_CFUNC_DEF("toString", 0, js_nodeList_toString) -}; - -#if 0 -static void -js_nodeList_finalizer(JSRuntime *rt, JSValue val) -{ - REF_JS(val); - - void *node = js_nodeList_GetOpaque(val); - - js_nodeList_SetOpaque(val, nullptr); - map_nodelist.erase(node); -} - -static JSClassDef js_nodeList_class = { - "nodeList", - js_nodeList_finalizer -}; -#endif - -JSValue -getNodeList(JSContext *ctx, void *node) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - auto node_find = map_nodelist.find(node); - - if (node_find != map_nodelist.end()) { - JSValue r = JS_DupValue(ctx, node_find->second); - RETURN_JS(r); - } - - JSValue nodeList_obj = JS_NewArray(ctx); - JS_SetPropertyFunctionList(ctx, nodeList_obj, js_nodeList_proto_funcs, countof(js_nodeList_proto_funcs)); - - map_nodelist[node] = nodeList_obj; - js_nodeList_SetOpaque(nodeList_obj, node); - js_nodeList_set_items(ctx, nodeList_obj, node); - JSValue rr = JS_DupValue(ctx, nodeList_obj); - - RETURN_JS(rr); -} -#endif diff --git a/src/ecmascript/quickjs/screen.cpp b/src/ecmascript/quickjs/screen.cpp deleted file mode 100644 index 67c8dcda..00000000 --- a/src/ecmascript/quickjs/screen.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* The QuickJS screen object implementation. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "elinks.h" - -#include "bfu/dialog.h" -#include "cache/cache.h" -#include "cookies/cookies.h" -#include "dialogs/menu.h" -#include "dialogs/status.h" -#include "document/html/frames.h" -#include "document/document.h" -#include "document/forms.h" -#include "document/view.h" -#include "ecmascript/ecmascript.h" -#include "ecmascript/quickjs.h" -#include "ecmascript/quickjs/screen.h" -#include "ecmascript/quickjs/window.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/memory.h" -#include "util/string.h" -#include "viewer/text/draw.h" -#include "viewer/text/form.h" -#include "viewer/text/link.h" -#include "viewer/text/vs.h" - -#ifndef CONFIG_LIBDOM - -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -static JSClassID js_screen_class_id; - -static JSValue -js_screen_get_property_availHeight(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; - struct document_view *doc_view = vs->doc_view; - - if (!doc_view) { - return JS_UNDEFINED; - } - - return JS_NewInt32(ctx, doc_view->box.height * 16); -} - -static JSValue -js_screen_get_property_availWidth(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; - struct document_view *doc_view = vs->doc_view; - - if (!doc_view) { - return JS_UNDEFINED; - } - - return JS_NewInt32(ctx, doc_view->box.width * 8); -} - -static JSValue -js_screen_get_property_height(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; - struct document_view *doc_view = vs->doc_view; - - if (!doc_view) { - return JS_UNDEFINED; - } - - struct session *ses = doc_view->session; - - if (!ses) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_UNDEFINED; - } - - return JS_NewInt32(ctx, ses->tab->term->height * 16); -} - -static JSValue -js_screen_get_property_width(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; - struct document_view *doc_view = vs->doc_view; - - if (!doc_view) { - return JS_UNDEFINED; - } - - struct session *ses = doc_view->session; - - if (!ses) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_UNDEFINED; - } - - return JS_NewInt32(ctx, ses->tab->term->width * 8); -} - -static JSValue -js_screen_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, "[screen object]"); -} - -static const JSCFunctionListEntry js_screen_proto_funcs[] = { - JS_CGETSET_DEF("availHeight", js_screen_get_property_availHeight, nullptr), - JS_CGETSET_DEF("availWidth", js_screen_get_property_availWidth, nullptr), - JS_CGETSET_DEF("height", js_screen_get_property_height, nullptr), - JS_CGETSET_DEF("width", js_screen_get_property_width, nullptr), - JS_CFUNC_DEF("toString", 0, js_screen_toString) -}; - -static JSClassDef js_screen_class = { - "screen", -}; - -int -js_screen_init(JSContext *ctx) -{ - JSValue screen_proto; - - /* create the screen class */ - JS_NewClassID(&js_screen_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_screen_class_id, &js_screen_class); - - JSValue global_obj = JS_GetGlobalObject(ctx); - REF_JS(global_obj); - - screen_proto = JS_NewObject(ctx); - REF_JS(screen_proto); - - JS_SetPropertyFunctionList(ctx, screen_proto, js_screen_proto_funcs, countof(js_screen_proto_funcs)); - JS_SetClassProto(ctx, js_screen_class_id, screen_proto); - - JS_SetPropertyStr(ctx, global_obj, "screen", JS_DupValue(ctx, screen_proto)); - - JS_FreeValue(ctx, global_obj); - REF_JS(global_obj); - - return 0; -} -#endif diff --git a/src/ecmascript/quickjs/unibar.cpp b/src/ecmascript/quickjs/unibar.cpp deleted file mode 100644 index 259453d0..00000000 --- a/src/ecmascript/quickjs/unibar.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* The quickjs unibar objects implementation. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "elinks.h" - -#include "bfu/dialog.h" -#include "cache/cache.h" -#include "cookies/cookies.h" -#include "dialogs/menu.h" -#include "dialogs/status.h" -#include "document/html/frames.h" -#include "document/document.h" -#include "document/forms.h" -#include "document/view.h" -#include "ecmascript/ecmascript.h" -#include "ecmascript/quickjs.h" -#include "ecmascript/quickjs/unibar.h" -#include "ecmascript/quickjs/window.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/memory.h" -#include "util/string.h" -#include "viewer/text/draw.h" -#include "viewer/text/form.h" -#include "viewer/text/link.h" -#include "viewer/text/vs.h" - -#ifndef CONFIG_LIBDOM - -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -static JSClassID js_menubar_class_id; -static JSClassID js_statusbar_class_id; - -static JSValue -js_unibar_get_property_visible(JSContext *ctx, JSValueConst this_val, int magic) -{ -#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; - struct document_view *doc_view = vs->doc_view; - - if (!doc_view) { - return JS_UNDEFINED; - } - - struct session_status *status = &doc_view->session->status; - -#define unibar_fetch(bar) \ - status->force_show_##bar##_bar >= 0 \ - ? status->force_show_##bar##_bar \ - : status->show_##bar##_bar - switch (magic) { - case 0: - return JS_NewBool(ctx, unibar_fetch(status)); - case 1: - return JS_NewBool(ctx, unibar_fetch(title)); - default: - return JS_NewBool(ctx, 0); - } -#undef unibar_fetch -} - -static JSValue -js_unibar_set_property_visible(JSContext *ctx, JSValueConst this_val, JSValue val, int magic) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - struct view_state *vs = interpreter->vs; - struct document_view *doc_view = vs->doc_view; - - if (!doc_view) { - return JS_UNDEFINED; - } - - struct session_status *status = &doc_view->session->status; - - switch (magic) { - case 0: - status->force_show_status_bar = JS_ToBool(ctx, val); - break; - case 1: - status->force_show_title_bar = JS_ToBool(ctx, val); - break; - default: - break; - } - register_bottom_half(update_status, NULL); - - return JS_UNDEFINED; -} - -static JSValue -js_menubar_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, "[menubar object]"); -} - -static JSValue -js_statusbar_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, "[statusbar object]"); -} - -static const JSCFunctionListEntry js_menubar_proto_funcs[] = { - JS_CGETSET_MAGIC_DEF("visible", js_unibar_get_property_visible, js_unibar_set_property_visible, 1), - JS_CFUNC_DEF("toString", 0, js_menubar_toString) -}; - -static const JSCFunctionListEntry js_statusbar_proto_funcs[] = { - JS_CGETSET_MAGIC_DEF("visible", js_unibar_get_property_visible, js_unibar_set_property_visible, 0), - JS_CFUNC_DEF("toString", 0, js_statusbar_toString) -}; - -static JSClassDef js_menubar_class = { - "menubar", -}; - -static JSClassDef js_statusbar_class = { - "statusbar", -}; - -int -js_unibar_init(JSContext *ctx) -{ - JSValue menubar_proto; - JSValue statusbar_proto; - - /* create the menubar class */ - JS_NewClassID(&js_menubar_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_menubar_class_id, &js_menubar_class); - - JSValue global_obj = JS_GetGlobalObject(ctx); - REF_JS(global_obj); - - menubar_proto = JS_NewObject(ctx); - REF_JS(menubar_proto); - - JS_SetPropertyFunctionList(ctx, menubar_proto, js_menubar_proto_funcs, countof(js_menubar_proto_funcs)); - - JS_SetClassProto(ctx, js_menubar_class_id, menubar_proto); - JS_SetPropertyStr(ctx, global_obj, "menubar", JS_DupValue(ctx, menubar_proto)); - - /* create the statusbar class */ - JS_NewClassID(&js_statusbar_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_statusbar_class_id, &js_statusbar_class); - - statusbar_proto = JS_NewObject(ctx); - REF_JS(statusbar_proto); - - JS_SetPropertyFunctionList(ctx, statusbar_proto, js_statusbar_proto_funcs, countof(js_statusbar_proto_funcs)); - - JS_SetClassProto(ctx, js_statusbar_class_id, statusbar_proto); - JS_SetPropertyStr(ctx, global_obj, "statusbar", JS_DupValue(ctx, statusbar_proto)); - - JS_FreeValue(ctx, global_obj); - - return 0; -} -#endif diff --git a/src/ecmascript/quickjs/window.cpp b/src/ecmascript/quickjs/window.cpp deleted file mode 100644 index 200f3c63..00000000 --- a/src/ecmascript/quickjs/window.cpp +++ /dev/null @@ -1,779 +0,0 @@ -/* The Quickjs window object implementation. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "elinks.h" - -#include "bfu/dialog.h" -#include "cache/cache.h" -#include "cookies/cookies.h" -#include "dialogs/menu.h" -#include "dialogs/status.h" -#include "document/html/frames.h" -#include "document/document.h" -#include "document/forms.h" -#include "document/view.h" -#include "ecmascript/ecmascript.h" -#include "ecmascript/quickjs.h" -#include "ecmascript/quickjs/heartbeat.h" -#include "ecmascript/quickjs/message.h" -#include "ecmascript/quickjs/window.h" -#include "ecmascript/timer.h" -#include "intl/libintl.h" -#include "main/select.h" -#include "main/timer.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/memory.h" -#include "util/string.h" -#include "viewer/text/draw.h" -#include "viewer/text/form.h" -#include "viewer/text/link.h" -#include "viewer/text/vs.h" - -#ifndef CONFIG_LIBDOM - -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -static JSClassID js_window_class_id; - -struct listener { - LIST_HEAD(struct listener); - char *typ; - JSValue fun; -}; - -struct el_window { - struct ecmascript_interpreter *interpreter; - JSValue thisval; - LIST_OF(struct listener) listeners; - JSValue onmessage; -}; - -struct el_message { - JSValue messageObject; - struct el_window *elwin; -}; - -static void -js_window_finalize(JSRuntime *rt, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(val); - - struct el_window *elwin = (struct el_window *)JS_GetOpaque(val, js_window_class_id); - - if (elwin) { - struct listener *l; - - foreach(l, elwin->listeners) { - mem_free_set(&l->typ, NULL); - } - free_list(elwin->listeners); - mem_free(elwin); - } -} - -static void -js_window_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(val); - - struct el_window *elwin = (struct el_window *)JS_GetOpaque(val, js_window_class_id); - - if (elwin) { - JS_MarkValue(rt, elwin->thisval, mark_func); - JS_MarkValue(rt, elwin->onmessage, mark_func); - - if (elwin->interpreter->vs && elwin->interpreter->vs->doc_view) { - struct document *doc = elwin->interpreter->vs->doc_view->document; - - struct ecmascript_timeout *et; - - foreach (et, doc->timeouts) { - - JS_MarkValue(rt, et->fun, mark_func); - } - } - - struct listener *l; - - foreach (l, elwin->listeners) { - JS_MarkValue(rt, l->fun, mark_func); - } - } -} - -/* @window_funcs{"open"} */ -JSValue -js_window_open(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct view_state *vs; - struct document_view *doc_view; - struct session *ses; - const char *frame = NULL; - char *url, *url2; - struct uri *uri; - static time_t ratelimit_start; - static int ratelimit_count; - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - vs = interpreter->vs; - doc_view = vs->doc_view; - ses = doc_view->session; - - if (get_opt_bool("ecmascript.block_window_opening", ses)) { -#ifdef CONFIG_LEDS - set_led_value(ses->status.popup_led, 'P'); -#endif - return JS_UNDEFINED; - } - - if (argc < 1) return JS_UNDEFINED; - - /* Ratelimit window opening. Recursive window.open() is very nice. - * We permit at most 20 tabs in 2 seconds. The ratelimiter is very - * rough but shall suffice against the usual cases. */ - if (!ratelimit_start || time(NULL) - ratelimit_start > 2) { - ratelimit_start = time(NULL); - ratelimit_count = 0; - } else { - ratelimit_count++; - if (ratelimit_count > 20) { - return JS_UNDEFINED; - } - } - - const char *str; - size_t len; - - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - - url = stracpy(str); - JS_FreeCString(ctx, str); - - if (!url) { - return JS_UNDEFINED; - } - trim_chars(url, ' ', 0); - url2 = join_urls(doc_view->document->uri, url); - mem_free(url); - - if (!url2) { - return JS_UNDEFINED; - } - - if (argc > 1) { - size_t len2; - frame = JS_ToCStringLen(ctx, &len2, argv[1]); - - if (!frame) { - mem_free(url2); - return JS_EXCEPTION; - } - } - - /* TODO: Support for window naming and perhaps some window features? */ - - uri = get_uri(url2, URI_NONE); - mem_free(url2); - if (!uri) { - if (frame) JS_FreeCString(ctx, frame); - return JS_UNDEFINED; - } - - JSValue ret; - - if (frame && *frame && c_strcasecmp(frame, "_blank")) { - struct delayed_open *deo = (struct delayed_open *)mem_calloc(1, sizeof(*deo)); - - if (deo) { - deo->ses = ses; - deo->uri = get_uri_reference(uri); - deo->target = stracpy(frame); - register_bottom_half(delayed_goto_uri_frame, deo); - ret = JS_TRUE; - goto end; - } - } - - if (!get_cmd_opt_bool("no-connect") - && !get_cmd_opt_bool("no-home") - && !get_cmd_opt_bool("anonymous") - && can_open_in_new(ses->tab->term)) { - open_uri_in_new_window(ses, uri, NULL, ENV_ANY, - CACHE_MODE_NORMAL, TASK_NONE); - ret = JS_TRUE; - } else { - /* When opening a new tab, we might get rerendered, losing our - * context and triggerring a disaster, so postpone that. */ - struct delayed_open *deo = (struct delayed_open *)mem_calloc(1, sizeof(*deo)); - - if (deo) { - deo->ses = ses; - deo->uri = get_uri_reference(uri); - register_bottom_half(delayed_open, deo); - ret = JS_TRUE; - } else { - ret = JS_UNDEFINED; - } - } - -end: - done_uri(uri); - if (frame) JS_FreeCString(ctx, frame); - - return ret; -} - -/* @window_funcs{"setTimeout"} */ -JSValue -js_window_setTimeout(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#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); - int64_t timeout = 0; - JSValueConst func; - - if (argc != 2) { - return JS_UNDEFINED; - } - - if (JS_ToInt64(ctx, &timeout, argv[1])) { - return JS_EXCEPTION; - } - - if (timeout <= 0) { - return JS_UNDEFINED; - } - - func = argv[0]; - - if (JS_IsFunction(ctx, func)) { - timer_id_T id = ecmascript_set_timeout2q(interpreter, JS_DupValue(ctx, func), timeout); - - JS_FreeValue(ctx, func); - - return JS_NewInt64(ctx, reinterpret_cast(id)); - } - - if (JS_IsString(func)) { - const char *code = JS_ToCString(ctx, func); - - if (!code) { - return JS_EXCEPTION; - } - char *code2 = stracpy(code); - JS_FreeCString(ctx, code); - - if (code2) { - timer_id_T id = ecmascript_set_timeout(interpreter, code2, timeout); - - return JS_NewInt64(ctx, reinterpret_cast(id)); - } - } - - return JS_UNDEFINED; -} - -/* @window_funcs{"clearTimeout"} */ -JSValue -js_window_clearTimeout(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) { - return JS_UNDEFINED; - } - int64_t number; - - if (JS_ToInt64(ctx, &number, argv[0])) { - return JS_UNDEFINED; - } - - timer_id_T id = reinterpret_cast(number); - - if (found_in_map_timer(id)) { - struct ecmascript_timeout *t = (struct ecmascript_timeout *)(id->data); - kill_timer(&t->tid); - done_string(&t->code); - del_from_list(t); - mem_free(t); - } - - return JS_UNDEFINED; -} - - -static JSValue -js_window_get_property_closed(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - return JS_FALSE; -} - -static JSValue -js_window_get_property_parent(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - /* XXX: It would be nice if the following worked, yes. - * The problem is that we get called at the point where - * document.frame properties are going to be mostly NULL. - * But the problem is deeper because at that time we are - * yet building scrn_frames so our parent might not be there - * yet (XXX: is this true?). The true solution will be to just - * have struct document_view *(document_view.parent). --pasky */ - /* FIXME: So now we alias window.parent to window.top, which is - * INCORRECT but works for the most common cases of just two - * frames. Better something than nothing. */ - - return JS_UNDEFINED; -} - -static JSValue -js_window_get_property_self(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - JSValue r = JS_DupValue(ctx, this_val); - - RETURN_JS(r); -} - -static JSValue -js_window_get_property_status(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - return JS_UNDEFINED; -} - -static JSValue -js_window_set_property_status(JSContext *ctx, JSValueConst this_val, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(val); - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - struct view_state *vs = interpreter->vs; - - if (!vs) { - return JS_UNDEFINED; - } - size_t len; - const char *str = JS_ToCStringLen(ctx, &len, val); - - if (!str) { - return JS_EXCEPTION; - } - char *text = stracpy(str); - JS_FreeCString(ctx, str); - - mem_free_set(&vs->doc_view->session->status.window_status, text); - print_screen_status(vs->doc_view->session); - - return JS_UNDEFINED; -} - -static JSValue -js_window_get_property_top(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct document_view *doc_view; - struct document_view *top_view; - JSValue newjsframe; - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - struct view_state *vs = interpreter->vs; - - if (!vs) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); -#endif - return JS_UNDEFINED; - } - doc_view = vs->doc_view; - top_view = doc_view->session->doc_view; - - assert(top_view && top_view->vs); - if (top_view->vs->ecmascript_fragile) - ecmascript_reset_state(top_view->vs); - if (!top_view->vs->ecmascript) { - return JS_UNDEFINED; - } - newjsframe = JS_GetGlobalObject((JSContext *)top_view->vs->ecmascript->backend_data); - - /* Keep this unrolled this way. Will have to check document.domain - * JS property. */ - /* Note that this check is perhaps overparanoid. If top windows - * is alien but some other child window is not, we should still - * let the script walk thru. That'd mean moving the check to - * other individual properties in this switch. */ - if (compare_uri(vs->uri, top_view->vs->uri, URI_HOST)) { - return newjsframe; - } - /* else */ - /****X*X*X*** SECURITY VIOLATION! RED ALERT, SHIELDS UP! ***X*X*X****\ - |* (Pasky was apparently looking at the Links2 JS code . ___ ^.^ *| - \* for too long.) `.(,_,)\o/ */ - return JS_UNDEFINED; -} - -JSValue -js_window_alert(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#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); - - assert(interpreter); - struct view_state *vs; - const char *str; - char *string; - size_t len; - - vs = interpreter->vs; - - if (argc != 1) - return JS_UNDEFINED; - - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - - string = stracpy(str); - JS_FreeCString(ctx, str); - - info_box(vs->doc_view->session->tab->term, MSGBOX_FREE_TEXT, - N_("JavaScript Alert"), ALIGN_CENTER, string); - - return JS_UNDEFINED; -} - -static JSValue -js_window_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, "[window object]"); -} - -static JSValue -js_window_addEventListener(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#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 el_window *elwin = (struct el_window *)(JS_GetOpaque(this_val, js_window_class_id)); - - if (!elwin) { - elwin = (struct el_window *)mem_calloc(1, sizeof(*elwin)); - - if (!elwin) { - return JS_EXCEPTION; - } - init_list(elwin->listeners); - elwin->interpreter = interpreter; - elwin->thisval = JS_DupValue(ctx, this_val); - JS_SetOpaque(this_val, elwin); - } - - if (argc < 2) { - return JS_UNDEFINED; - } - const char *str; - size_t len; - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - char *method = stracpy(str); - JS_FreeCString(ctx, str); - - if (!method) { - return JS_EXCEPTION; - } - - JSValue fun = argv[1]; - struct listener *l; - - foreach(l, elwin->listeners) { - if (strcmp(l->typ, method)) { - continue; - } - if (JS_VALUE_GET_PTR(l->fun) == JS_VALUE_GET_PTR(fun)) { - mem_free(method); - return JS_UNDEFINED; - } - } - struct listener *n = (struct listener *)mem_calloc(1, sizeof(*n)); - - if (n) { - n->typ = method; - n->fun = JS_DupValue(ctx, argv[1]); - add_to_list_end(elwin->listeners, n); - } - return JS_UNDEFINED; -} - -static JSValue -js_window_removeEventListener(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct el_window *elwin = (struct el_window *)(JS_GetOpaque(this_val, js_window_class_id)); - - if (!elwin) { - return JS_NULL; - } - - if (argc < 2) { - return JS_UNDEFINED; - } - const char *str; - size_t len; - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - char *method = stracpy(str); - JS_FreeCString(ctx, str); - - if (!method) { - return JS_EXCEPTION; - } - JSValue fun = argv[1]; - struct listener *l; - - foreach(l, elwin->listeners) { - if (strcmp(l->typ, method)) { - continue; - } - if (JS_VALUE_GET_PTR(l->fun) == JS_VALUE_GET_PTR(fun)) { - del_from_list(l); - mem_free_set(&l->typ, NULL); - mem_free(l); - mem_free(method); - return JS_UNDEFINED; - } - } - mem_free(method); - return JS_UNDEFINED; -} - -static void -onmessage_run(void *data) -{ - struct el_message *mess = (struct el_message *)data; - - if (mess) { - struct el_window *elwin = mess->elwin; - - if (!elwin) { - mem_free(mess); - return; - } - - struct ecmascript_interpreter *interpreter = elwin->interpreter; - JSContext *ctx = (JSContext *)interpreter->backend_data; - interpreter->heartbeat = add_heartbeat(interpreter); - - struct listener *l; - - foreach(l, elwin->listeners) { - if (strcmp(l->typ, "message")) { - continue; - } - JSValue func = JS_DupValue(ctx, l->fun); - JSValue arg = JS_DupValue(ctx, mess->messageObject); - JSValue ret = JS_Call(ctx, func, elwin->thisval, 1, (JSValueConst *) &arg); - JS_FreeValue(ctx, ret); - JS_FreeValue(ctx, func); - JS_FreeValue(ctx, arg); - } - if (JS_IsFunction(ctx, elwin->onmessage)) { - JSValue func = JS_DupValue(ctx, elwin->onmessage); - JSValue arg = JS_DupValue(ctx, mess->messageObject); - JSValue ret = JS_Call(ctx, func, elwin->thisval, 1, (JSValueConst *) &arg); - JS_FreeValue(ctx, ret); - JS_FreeValue(ctx, func); - JS_FreeValue(ctx, arg); - } - done_heartbeat(interpreter->heartbeat); - check_for_rerender(interpreter, "window_message"); - } -} - -static JSValue -js_window_postMessage(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - struct el_window *elwin = (struct el_window *)(JS_GetOpaque(this_val, js_window_class_id)); - - if (argc < 2) { - return JS_UNDEFINED; - } - const char *str; - size_t len; - str = JS_ToCStringLen(ctx, &len, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - char *data = stracpy(str); - JS_FreeCString(ctx, str); - - str = JS_ToCStringLen(ctx, &len, argv[1]); - if (!str) { - mem_free_if(data); - return JS_EXCEPTION; - } - char *targetOrigin = stracpy(str); - JS_FreeCString(ctx, str); - char *source = stracpy("TODO"); - - JSValue val = get_messageEvent(ctx, data, targetOrigin, source); - - mem_free_if(data); - mem_free_if(targetOrigin); - mem_free_if(source); - - if (JS_IsNull(val) || !elwin) { - return JS_UNDEFINED; - } - struct el_message *mess = (struct el_message *)mem_calloc(1, sizeof(*mess)); - if (!mess) { - return JS_EXCEPTION; - } - mess->messageObject = JS_DupValue(ctx, val); - mess->elwin = elwin; - register_bottom_half(onmessage_run, mess); - - return JS_UNDEFINED; -} - -static const JSCFunctionListEntry js_window_proto_funcs[] = { - JS_CGETSET_DEF("closed", js_window_get_property_closed, nullptr), - JS_CGETSET_DEF("parent", js_window_get_property_parent, nullptr), - JS_CGETSET_DEF("self", js_window_get_property_self, nullptr), - JS_CGETSET_DEF("status", js_window_get_property_status, js_window_set_property_status), - JS_CGETSET_DEF("top", js_window_get_property_top, nullptr), - JS_CGETSET_DEF("window", js_window_get_property_self, nullptr), - JS_CFUNC_DEF("addEventListener", 3, js_window_addEventListener), - JS_CFUNC_DEF("alert", 1, js_window_alert), - JS_CFUNC_DEF("clearTimeout", 1, js_window_clearTimeout), - JS_CFUNC_DEF("open", 3, js_window_open), - JS_CFUNC_DEF("postMessage", 3, js_window_postMessage), - JS_CFUNC_DEF("removeEventListener", 3, js_window_removeEventListener), - JS_CFUNC_DEF("setTimeout", 2, js_window_setTimeout), - JS_CFUNC_DEF("toString", 0, js_window_toString) -}; - -static JSClassDef js_window_class = { - "window", - .finalizer = js_window_finalize, - .gc_mark = js_window_mark, -}; - -int -js_window_init(JSContext *ctx) -{ - JSValue window_proto; - - /* create the window class */ - JS_NewClassID(&js_window_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_window_class_id, &js_window_class); - - JSValue global_obj = JS_GetGlobalObject(ctx); - REF_JS(global_obj); - - window_proto = JS_NewObject(ctx); - REF_JS(window_proto); - JS_SetPropertyFunctionList(ctx, window_proto, js_window_proto_funcs, countof(js_window_proto_funcs)); - - JS_SetClassProto(ctx, js_window_class_id, window_proto); - JS_SetPropertyStr(ctx, global_obj, "window", JS_DupValue(ctx, window_proto)); - - JS_SetPropertyFunctionList(ctx, global_obj, js_window_proto_funcs, countof(js_window_proto_funcs)); - - JS_FreeValue(ctx, global_obj); - - return 0; -} -#endif diff --git a/src/ecmascript/quickjs/xhr.cpp b/src/ecmascript/quickjs/xhr.cpp deleted file mode 100644 index 7fe57cbe..00000000 --- a/src/ecmascript/quickjs/xhr.cpp +++ /dev/null @@ -1,1616 +0,0 @@ -/* - * QuickJS libuv bindings - * - * Copyright (c) 2019-present Saúl Ibarra Corretgé - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/* The QuickJS xhr object implementation. */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include - -#include "elinks.h" - -#include "bfu/dialog.h" -#include "cache/cache.h" -#include "cookies/cookies.h" -#include "dialogs/menu.h" -#include "dialogs/status.h" -#include "document/html/frames.h" -#include "document/document.h" -#include "document/forms.h" -#include "document/view.h" -#include "ecmascript/ecmascript.h" -#include "ecmascript/quickjs.h" -#include "ecmascript/quickjs/heartbeat.h" -#include "ecmascript/quickjs/xhr.h" -#include "ecmascript/timer.h" -#include "intl/libintl.h" -#include "main/select.h" -#include "main/timer.h" -#include "network/connection.h" -#include "osdep/newwin.h" -#include "osdep/sysname.h" -#include "protocol/http/http.h" -#include "protocol/uri.h" -#include "session/download.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/memory.h" -#include "util/string.h" -#include "viewer/text/draw.h" -#include "viewer/text/form.h" -#include "viewer/text/link.h" -#include "viewer/text/vs.h" - -#include - -#include -#include -#include -#include - -#ifndef CONFIG_LIBDOM - -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -enum { - XHR_EVENT_ABORT = 0, - XHR_EVENT_ERROR, - XHR_EVENT_LOAD, - XHR_EVENT_LOAD_END, - XHR_EVENT_LOAD_START, - XHR_EVENT_PROGRESS, - XHR_EVENT_READY_STATE_CHANGED, - XHR_EVENT_TIMEOUT, - XHR_EVENT_MAX, -}; - -enum { - XHR_RSTATE_UNSENT = 0, - XHR_RSTATE_OPENED, - XHR_RSTATE_HEADERS_RECEIVED, - XHR_RSTATE_LOADING, - XHR_RSTATE_DONE, -}; - -enum { - XHR_RTYPE_DEFAULT = 0, - XHR_RTYPE_TEXT, - XHR_RTYPE_ARRAY_BUFFER, - XHR_RTYPE_JSON, -}; - -enum { - GET = 1, - HEAD = 2, - POST = 3 -}; - -struct classcomp { - bool operator() (const std::string& lhs, const std::string& rhs) const - { - return strcasecmp(lhs.c_str(), rhs.c_str()) < 0; - } -}; - -static char *normalize(char *value); - -static char * -normalize(char *value) -{ - char *ret = value; - size_t index = strspn(ret, "\r\n\t "); - ret += index; - char *end = strchr(ret, 0); - - do { - --end; - - if (*end == '\r' || *end == '\n' || *end == '\t' || *end == ' ') { - *end = '\0'; - } else { - break; - } - } while (end > ret); - - return ret; -} - -static bool -valid_header(const char *header) -{ - if (!*header) { - return false; - } - - for (const char *c = header; *c; c++) { - if (*c < 33 || *c > 127) { - return false; - } - } - return (NULL == strpbrk(header, "()<>@,;:\\\"/[]?={}")); -} - -static bool -forbidden_header(const char *header) -{ - const char *bad[] = { - "Accept-Charset" - "Accept-Encoding", - "Access-Control-Request-Headers", - "Access-Control-Request-Method", - "Connection", - "Content-Length", - "Cookie", - "Cookie2", - "Date", - "DNT", - "Expect", - "Host", - "Keep-Alive", - "Origin", - "Referer", - "Set-Cookie", - "TE", - "Trailer", - "Transfer-Encoding", - "Upgrade", - "Via", - NULL - }; - - for (int i = 0; bad[i]; i++) { - if (!strcasecmp(header, bad[i])) { - return true; - } - } - - if (!strncasecmp(header, "proxy-", 6)) { - return true; - } - - if (!strncasecmp(header, "sec-", 4)) { - return true; - } - - return false; -} - -struct listener { - LIST_HEAD(struct listener); - char *typ; - JSValue fun; -}; - -typedef struct { - std::map requestHeaders; - std::map responseHeaders; - struct download download; - struct ecmascript_interpreter *interpreter; - - LIST_OF(struct listener) listeners; - - JSValue events[XHR_EVENT_MAX]; - JSValue thisVal; - struct uri *uri; - bool sent; - bool async; - short response_type; - unsigned long timeout; - unsigned short ready_state; - - int status; - char *status_text; - char *response_text; - size_t response_length; - - struct { - JSValue url; - JSValue headers; - JSValue response; - } result; - - char *responseURL; - int method; -} Xhr; - -static JSClassID xhr_class_id; - -static void onload_run(void *data); -static void onloadend_run(void *data); -static void onreadystatechange_run(void *data); -static void ontimeout_run(void *data); - -static void -onload_run(void *data) -{ - Xhr *x = (Xhr *)data; - - if (x) { - struct ecmascript_interpreter *interpreter = x->interpreter; - JSContext *ctx = (JSContext *)interpreter->backend_data; - interpreter->heartbeat = add_heartbeat(interpreter); - - struct listener *l; - - foreach(l, x->listeners) { - if (strcmp(l->typ, "load")) { - continue; - } - JSValue func = JS_DupValue(ctx, l->fun); - JSValue arg = JS_UNDEFINED; - JSValue ret = JS_Call(ctx, func, x->thisVal, 1, (JSValueConst *) &arg); - JS_FreeValue(ctx, ret); - JS_FreeValue(ctx, func); - JS_FreeValue(ctx, arg); - } - JSValue event_func = x->events[XHR_EVENT_LOAD]; - - if (JS_IsFunction(ctx, event_func)) { - JSValue func = JS_DupValue(ctx, event_func); - JSValue arg = JS_UNDEFINED; - JSValue ret = JS_Call(ctx, func, x->thisVal, 1, (JSValueConst *) &arg); - JS_FreeValue(ctx, ret); - JS_FreeValue(ctx, func); - JS_FreeValue(ctx, arg); - } - done_heartbeat(interpreter->heartbeat); - check_for_rerender(interpreter, "xhr_onload"); - } -} - -static void -onloadend_run(void *data) -{ - Xhr *x = (Xhr *)data; - - if (x) { - struct ecmascript_interpreter *interpreter = x->interpreter; - JSContext *ctx = (JSContext *)interpreter->backend_data; - interpreter->heartbeat = add_heartbeat(interpreter); - - struct listener *l; - - foreach(l, x->listeners) { - if (strcmp(l->typ, "loadend")) { - continue; - } - JSValue func = JS_DupValue(ctx, l->fun); - JSValue arg = JS_UNDEFINED; - JSValue ret = JS_Call(ctx, func, x->thisVal, 1, (JSValueConst *) &arg); - JS_FreeValue(ctx, ret); - JS_FreeValue(ctx, func); - JS_FreeValue(ctx, arg); - } - JSValue event_func = x->events[XHR_EVENT_LOAD_END]; - - if (JS_IsFunction(ctx, event_func)) { - JSValue func = JS_DupValue(ctx, event_func); - JSValue arg = JS_UNDEFINED; - JSValue ret = JS_Call(ctx, func, x->thisVal, 1, (JSValueConst *) &arg); - JS_FreeValue(ctx, ret); - JS_FreeValue(ctx, func); - JS_FreeValue(ctx, arg); - } - done_heartbeat(interpreter->heartbeat); - check_for_rerender(interpreter, "xhr_onloadend"); - } -} - -static void -onreadystatechange_run(void *data) -{ - Xhr *x = (Xhr *)data; - - if (x) { - struct ecmascript_interpreter *interpreter = x->interpreter; - JSContext *ctx = (JSContext *)interpreter->backend_data; - interpreter->heartbeat = add_heartbeat(interpreter); - - struct listener *l; - - foreach(l, x->listeners) { - if (strcmp(l->typ, "readystatechange")) { - continue; - } - JSValue func = JS_DupValue(ctx, l->fun); - JSValue arg = JS_UNDEFINED; - JSValue ret = JS_Call(ctx, func, x->thisVal, 1, (JSValueConst *) &arg); - JS_FreeValue(ctx, ret); - JS_FreeValue(ctx, func); - JS_FreeValue(ctx, arg); - } - JSValue event_func = x->events[XHR_EVENT_READY_STATE_CHANGED]; - - if (JS_IsFunction(ctx, event_func)) { - JSValue func = JS_DupValue(ctx, event_func); - JSValue arg = JS_UNDEFINED; - JSValue ret = JS_Call(ctx, func, x->thisVal, 1, (JSValueConst *) &arg); - JS_FreeValue(ctx, ret); - JS_FreeValue(ctx, func); - JS_FreeValue(ctx, arg); - } - done_heartbeat(interpreter->heartbeat); - check_for_rerender(interpreter, "xhr_onreadystatechange"); - } -} - -static void -ontimeout_run(void *data) -{ - Xhr *x = (Xhr *)data; - - if (x) { - struct ecmascript_interpreter *interpreter = x->interpreter; - JSContext *ctx = (JSContext *)interpreter->backend_data; - interpreter->heartbeat = add_heartbeat(interpreter); - - struct listener *l; - - foreach(l, x->listeners) { - if (strcmp(l->typ, "timeout")) { - continue; - } - JSValue func = JS_DupValue(ctx, l->fun); - JSValue arg = JS_UNDEFINED; - JSValue ret = JS_Call(ctx, func, x->thisVal, 1, (JSValueConst *) &arg); - JS_FreeValue(ctx, ret); - JS_FreeValue(ctx, func); - JS_FreeValue(ctx, arg); - } - JSValue event_func = x->events[XHR_EVENT_TIMEOUT]; - - if (JS_IsFunction(ctx, event_func)) { - JSValue func = JS_DupValue(ctx, event_func); - JSValue arg = JS_UNDEFINED; - JSValue ret = JS_Call(ctx, func, x->thisVal, 1, (JSValueConst *) &arg); - JS_FreeValue(ctx, ret); - JS_FreeValue(ctx, func); - JS_FreeValue(ctx, arg); - } - done_heartbeat(interpreter->heartbeat); - check_for_rerender(interpreter, "xhr_ontimeout"); - } -} - -static void -xhr_finalizer(JSRuntime *rt, JSValue val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(val); - - Xhr *x = (Xhr *)JS_GetOpaque(val, xhr_class_id); - - if (x) { - for (int i = 0; i < XHR_EVENT_MAX; i++) { - JS_FreeValueRT(rt, x->events[i]); - } - JS_FreeValueRT(rt, x->result.url); - JS_FreeValueRT(rt, x->result.headers); - JS_FreeValueRT(rt, x->result.response); - - if (x->uri) { - done_uri(x->uri); - } - mem_free_if(x->responseURL); - mem_free_if(x->status_text); - x->responseHeaders.clear(); - x->requestHeaders.clear(); - - struct listener *l; - - foreach(l, x->listeners) { - mem_free_set(&l->typ, NULL); - JS_FreeValueRT(rt, l->fun); - } - free_list(x->listeners); - - mem_free(x); - } -} - -static void -xhr_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(val); - - Xhr *x = (Xhr *)JS_GetOpaque(val, xhr_class_id); - - if (x) { - for (int i = 0; i < XHR_EVENT_MAX; i++) { - JS_MarkValue(rt, x->events[i], mark_func); - } - JS_MarkValue(rt, x->thisVal, mark_func); - JS_MarkValue(rt, x->result.url, mark_func); - JS_MarkValue(rt, x->result.headers, mark_func); - JS_MarkValue(rt, x->result.response, mark_func); - - struct listener *l; - - foreach(l, x->listeners) { - JS_MarkValue(rt, l->fun, mark_func); - } - } -} - -static JSClassDef xhr_class = { - "XMLHttpRequest", - .finalizer = xhr_finalizer, - .gc_mark = xhr_mark, -}; - -static Xhr * -xhr_get(JSContext *ctx, JSValueConst obj) -{ - REF_JS(obj); - - return (Xhr *)JS_GetOpaque2(ctx, obj, xhr_class_id); -} - -static const std::vector -explode(const std::string& s, const char& c) -{ - std::string buff{""}; - std::vector v; - - bool found = false; - for (auto n:s) { - if (found) { - buff += n; - continue; - } - if (n != c) { - buff += n; - } - else if (n == c && buff != "") { - v.push_back(buff); - buff = ""; - found = true; - } - } - - if (buff != "") { - v.push_back(buff); - } - - return v; -} - -static void -x_loading_callback(struct download *download, Xhr *x) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - - if (is_in_state(download->state, S_TIMEOUT)) { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s S_TIMEOUT\n", __FILE__, __FUNCTION__); -#endif - if (x->ready_state != XHR_RSTATE_DONE) { - x->ready_state = XHR_RSTATE_DONE; - register_bottom_half(onreadystatechange_run, x); - } - register_bottom_half(ontimeout_run, x); - register_bottom_half(onloadend_run, x); - } else if (is_in_result_state(download->state)) { - struct cache_entry *cached = download->cached; -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s is_in_result_state\n", __FILE__, __FUNCTION__); -#endif - if (!cached) { - return; - } - struct fragment *fragment = get_cache_fragment(cached); - - if (!fragment) { - return; - } - if (cached->head) { - std::istringstream headers(cached->head); - - std::string http; - int status; - std::string statusText; - - std::string line; - - std::getline(headers, line); - - std::istringstream linestream(line); - linestream >> http >> status >> statusText; - - while (1) { - std::getline(headers, line); - if (line.empty()) { - break; - } - std::vector v = explode(line, ':'); - if (v.size() == 2) { - char *value = stracpy(v[1].c_str()); - - if (!value) { - continue; - } - char *header = stracpy(v[0].c_str()); - if (!header) { - mem_free(value); - continue; - } - char *normalized_value = normalize(value); - bool found = false; - - for (auto h: x->responseHeaders) { - const std::string hh = h.first; - if (!strcasecmp(hh.c_str(), header)) { - x->responseHeaders[hh] = x->responseHeaders[hh] + ", " + normalized_value; - found = true; - break; - } - } - - if (!found) { - x->responseHeaders[header] = normalized_value; - } - mem_free(header); - mem_free(value); - } - } - x->status = status; - mem_free_set(&x->status_text, stracpy(statusText.c_str())); - } - mem_free_set(&x->response_text, memacpy(fragment->data, fragment->length)); - if (x->ready_state != XHR_RSTATE_DONE) { - x->ready_state = XHR_RSTATE_DONE; - register_bottom_half(onreadystatechange_run, x); - } - register_bottom_half(onloadend_run, x); - register_bottom_half(onload_run, x); - } else { -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s else\n", __FILE__, __FUNCTION__); -#endif - } -} - -static JSValue -xhr_constructor(JSContext *ctx, JSValueConst new_target, int argc, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(new_target); - - JSValue obj = JS_NewObjectClass(ctx, xhr_class_id); - REF_JS(obj); - - if (JS_IsException(obj)) { - return obj; - } - Xhr *x = (Xhr *)mem_calloc(1, sizeof(*x)); - - if (!x) { - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; - } - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - - x->interpreter = interpreter; - x->result.url = JS_NULL; - x->result.headers = JS_NULL; - x->result.response = JS_NULL; -// dbuf_init(&x->result.hbuf); -// dbuf_init(&x->result.bbuf); - x->ready_state = XHR_RSTATE_UNSENT; -// x->slist = NULL; - x->sent = false; - x->async = true; - - init_list(x->listeners); - - for (int i = 0; i < XHR_EVENT_MAX; i++) { - x->events[i] = JS_UNDEFINED; - } - JS_SetOpaque(obj, x); - x->thisVal = JS_DupValue(ctx, obj); - - return obj; -} - -static JSValue -xhr_event_get(JSContext *ctx, JSValueConst this_val, int magic) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - Xhr *x = xhr_get(ctx, this_val); - - if (!x) { - return JS_EXCEPTION; - } - - return JS_DupValue(ctx, x->events[magic]); -} - -static JSValue -xhr_event_set(JSContext *ctx, JSValueConst this_val, JSValueConst value, int magic) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(value); - - Xhr *x = xhr_get(ctx, this_val); - - if (!x) { - return JS_EXCEPTION; - } - - if (JS_IsFunction(ctx, value) || JS_IsUndefined(value) || JS_IsNull(value)) { - JS_FreeValue(ctx, x->events[magic]); - x->events[magic] = JS_DupValue(ctx, value); - } - return JS_UNDEFINED; -} - -static JSValue -xhr_readystate_get(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - Xhr *x = xhr_get(ctx, this_val); - - if (!x) { - return JS_EXCEPTION; - } - - return JS_NewInt32(ctx, x->ready_state); -} - -static JSValue -xhr_response_get(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - Xhr *x = xhr_get(ctx, this_val); - - if (!x) { - return JS_EXCEPTION; - } -// TODO - return JS_NULL; -#if 0 -// DynBuf *bbuf = &x->result.bbuf; - if (bbuf->size == 0) - return JS_NULL; - if (JS_IsNull(x->result.response)) { - switch (x->response_type) { - case XHR_RTYPE_DEFAULT: - case XHR_RTYPE_TEXT: - x->result.response = JS_NewStringLen(ctx, (char *) bbuf->buf, bbuf->size); - break; - case XHR_RTYPE_ARRAY_BUFFER: - x->result.response = JS_NewArrayBufferCopy(ctx, bbuf->buf, bbuf->size); - break; - case XHR_RTYPE_JSON: - // It's necessary to null-terminate the string passed to JS_ParseJSON. - dbuf_putc(bbuf, '\0'); - x->result.response = JS_ParseJSON(ctx, (char *) bbuf->buf, bbuf->size, ""); - break; - default: - abort(); - } - } - return JS_DupValue(ctx, x->result.response); -#endif -} - -static JSValue -xhr_responsetext_get(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - Xhr *x = xhr_get(ctx, this_val); - - if (!x) { - return JS_EXCEPTION; - } - -//DynBuf *bbuf = &x->result.bbuf; -// if (bbuf->size == 0) -// return JS_NULL; - if (!x->response_text) { - return JS_NULL; - } - - return JS_NewString(ctx, x->response_text); -} - -static JSValue -xhr_responsetype_get(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - Xhr *x = xhr_get(ctx, this_val); - - if (!x) { - return JS_EXCEPTION; - } - - switch (x->response_type) { - case XHR_RTYPE_DEFAULT: - return JS_NewString(ctx, ""); - case XHR_RTYPE_TEXT: - return JS_NewString(ctx, "text"); - case XHR_RTYPE_ARRAY_BUFFER: - return JS_NewString(ctx, "arraybuffer"); - case XHR_RTYPE_JSON: - return JS_NewString(ctx, "json"); - default: - return JS_NULL;//abort(); - } -} - -static JSValue -xhr_responsetype_set(JSContext *ctx, JSValueConst this_val, JSValueConst value) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(value); - - static const char array_buffer[] = "arraybuffer"; - static const char json[] = "json"; - static const char text[] = "text"; - - Xhr *x = xhr_get(ctx, this_val); - - if (!x) { - return JS_EXCEPTION; - } - - if (x->ready_state >= XHR_RSTATE_LOADING) { - JS_Throw(ctx, JS_NewString(ctx, "InvalidStateError")); - } - - const char *v = JS_ToCString(ctx, value); - - if (v) { - if (strncmp(array_buffer, v, sizeof(array_buffer) - 1) == 0) { - x->response_type = XHR_RTYPE_ARRAY_BUFFER; - } else if (strncmp(json, v, sizeof(json) - 1) == 0) { - x->response_type = XHR_RTYPE_JSON; - } else if (strncmp(text, v, sizeof(text) - 1) == 0) { - x->response_type = XHR_RTYPE_TEXT; - } else if (strlen(v) == 0) { - x->response_type = XHR_RTYPE_DEFAULT; - } - JS_FreeCString(ctx, v); - } - - return JS_UNDEFINED; -} - -static JSValue -xhr_responseurl_get(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - Xhr *x = xhr_get(ctx, this_val); - - if (!x) { - return JS_EXCEPTION; - } - - return JS_DupValue(ctx, x->result.url); -} - -static JSValue -xhr_status_get(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - Xhr *x = xhr_get(ctx, this_val); - - if (!x) { - return JS_EXCEPTION; - } - - return JS_NewInt32(ctx, x->status); -} - -static JSValue -xhr_statustext_get(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - Xhr *x = xhr_get(ctx, this_val); - - if (!x) { - return JS_EXCEPTION; - } - - return JS_NewString(ctx, x->status_text); -} - -static JSValue -xhr_timeout_get(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - Xhr *x = xhr_get(ctx, this_val); - - if (!x) { - return JS_EXCEPTION; - } - - return JS_NewInt32(ctx, x->timeout); -} - -static JSValue -xhr_timeout_set(JSContext *ctx, JSValueConst this_val, JSValueConst value) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(value); - - Xhr *x = xhr_get(ctx, this_val); - - if (!x || !x->async) { - return JS_EXCEPTION; - } - int32_t timeout; - - if (JS_ToInt32(ctx, &timeout, value)) { - return JS_EXCEPTION; - } - - x->timeout = timeout; - -// if (!x->sent) -// curl_easy_setopt(x->curl_h, CURLOPT_TIMEOUT_MS, timeout); - - return JS_UNDEFINED; -} - -static JSValue -xhr_upload_get(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - // TODO. - return JS_UNDEFINED; -} - -static JSValue -xhr_withcredentials_get(JSContext *ctx, JSValueConst this_val) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - // TODO. - return JS_UNDEFINED; -} - -static JSValue -xhr_withcredentials_set(JSContext *ctx, JSValueConst this_val, JSValueConst value) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - REF_JS(value); - // TODO. - return JS_UNDEFINED; -} - -static JSValue -xhr_abort(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - Xhr *x = xhr_get(ctx, this_val); - - if (!x) { - return JS_EXCEPTION; - } - x->ready_state = XHR_RSTATE_UNSENT; - x->status = 0; - mem_free_set(&x->status_text, NULL); - - if (x->download.conn) { - abort_connection(x->download.conn, connection_state(S_INTERRUPTED)); - } - //maybe_emit_event(x, XHR_EVENT_ABORT, JS_UNDEFINED); - return JS_UNDEFINED; -} - -static JSValue -xhr_addEventListener(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - Xhr *x = xhr_get(ctx, this_val); - - if (!x) { - return JS_EXCEPTION; - } - - if (argc < 2) { - return JS_UNDEFINED; - } - - const char *str = JS_ToCString(ctx, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - - char *method = stracpy(str); - JS_FreeCString(ctx, str); - - if (!method) { - return JS_EXCEPTION; - } - JSValueConst fun = argv[1]; - struct listener *l; - - foreach(l, x->listeners) { - if (strcmp(l->typ, method)) { - continue; - } - if (JS_VALUE_GET_PTR(l->fun) == JS_VALUE_GET_PTR(fun)) { - mem_free(method); - return JS_UNDEFINED; - } - } - struct listener *n = (struct listener *)mem_calloc(1, sizeof(*n)); - - if (n) { - n->typ = method; - n->fun = JS_DupValue(ctx, fun); - add_to_list_end(x->listeners, n); - } - return JS_UNDEFINED; -} - -static JSValue -xhr_removeEventListener(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - Xhr *x = xhr_get(ctx, this_val); - - if (!x) { - return JS_EXCEPTION; - } - - if (argc < 2) { - return JS_UNDEFINED; - } - const char *str = JS_ToCString(ctx, argv[0]); - - if (!str) { - return JS_EXCEPTION; - } - - char *method = stracpy(str); - JS_FreeCString(ctx, str); - - if (!method) { - return JS_EXCEPTION; - } - JSValueConst fun = argv[1]; - struct listener *l; - - foreach(l, x->listeners) { - if (strcmp(l->typ, method)) { - continue; - } - if (JS_VALUE_GET_PTR(l->fun) == JS_VALUE_GET_PTR(fun)) { - del_from_list(l); - mem_free_set(&l->typ, NULL); - JS_FreeValue(ctx, l->fun); - mem_free(l); - mem_free(method); - - return JS_UNDEFINED; - } - } - mem_free(method); - - return JS_UNDEFINED; -} - -static JSValue -xhr_getallresponseheaders(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - Xhr *x = xhr_get(ctx, this_val); - - if (!x) { - return JS_EXCEPTION; - } - std::string output = ""; - - for (auto h: x->responseHeaders) { - output += h.first + ": " + h.second + "\r\n"; - } - return JS_NewString(ctx, output.c_str()); -} - -static JSValue -xhr_getresponseheader(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - Xhr *x = xhr_get(ctx, this_val); - - if (!x) { - return JS_EXCEPTION; - } - const char *header_name = JS_ToCString(ctx, argv[0]); - - if (header_name) { - std::string output = ""; - for (auto h: x->responseHeaders) { - if (!strcasecmp(header_name, h.first.c_str())) { - output = h.second; - break; - } - } - JS_FreeCString(ctx, header_name); - if (!output.empty()) { - return JS_NewString(ctx, output.c_str()); - } - } - return JS_NULL; -} - -static JSValue -xhr_open(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - Xhr *x = xhr_get(ctx, this_val); - - if (!x) { - return JS_EXCEPTION; - } - // TODO: support username and password. - - if (x->ready_state == XHR_RSTATE_DONE) { -// if (x->slist) -// curl_slist_free_all(x->slist); - for (int i = 0; i < XHR_EVENT_MAX; i++) { - JS_FreeValue(ctx, x->events[i]); - } - x->status = 0; - mem_free_set(&x->status_text, NULL); - JS_FreeValue(ctx, x->result.url); - JS_FreeValue(ctx, x->result.headers); - JS_FreeValue(ctx, x->result.response); -// dbuf_free(&x->result.hbuf); -// dbuf_free(&x->result.bbuf); - -// dbuf_init(&x->result.hbuf); -// dbuf_init(&x->result.bbuf); - x->result.url = JS_NULL; - x->result.headers = JS_NULL; - x->result.response = JS_NULL; - x->ready_state = XHR_RSTATE_UNSENT; - //x->slist = NULL; - x->sent = false; - x->async = true; - - for (int i = 0; i < XHR_EVENT_MAX; i++) { - x->events[i] = JS_UNDEFINED; - } - mem_free_set(&x->response_text, NULL); - x->response_length = 0; - } - - if (x->ready_state < XHR_RSTATE_OPENED) { - JSValue method = argv[0]; - JSValue url = argv[1]; - JSValue async = argv[2]; - const char *method_str = JS_ToCString(ctx, method); - const char *url_str = JS_ToCString(ctx, url); - - if (argc == 3) { - x->async = JS_ToBool(ctx, async); - } -// if (strncasecmp(head_method, method_str, sizeof(head_method) - 1) == 0) -// curl_easy_setopt(x->curl_h, CURLOPT_NOBODY, 1L); -// else -// curl_easy_setopt(x->curl_h, CURLOPT_CUSTOMREQUEST, method_str); -// curl_easy_setopt(x->curl_h, CURLOPT_URL, url_str); - - const char *allowed[] = { "", "GET", "HEAD", "POST", NULL }; - bool method_ok = false; - - for (int i = 1; allowed[i]; i++) { - if (!strcasecmp(allowed[i], method_str)) { - method_ok = true; - x->method = i; - break; - } - } - mem_free_set(&x->responseURL, stracpy(url_str)); - JS_FreeCString(ctx, method_str); - JS_FreeCString(ctx, url_str); - - if (!method_ok || !x->responseURL) { - return JS_UNDEFINED; - } - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - struct view_state *vs = interpreter->vs; - - if (!strchr(x->responseURL, '/')) { - char *ref = get_uri_string(vs->uri, URI_DIR_LOCATION | URI_PATH); - - if (ref) { - char *slash = strrchr(ref, '/'); - - if (slash) { - *slash = '\0'; - } - char *url = straconcat(ref, "/", x->responseURL, NULL); - - if (url) { - x->uri = get_uri(url, URI_NONE); - mem_free(url); - } - mem_free(ref); - } - } - - if (!x->uri) { - x->uri = get_uri(x->responseURL, URI_NONE); - } - - if (!x->uri) { - return JS_UNDEFINED; - } - - char *username = NULL; - char *password = NULL; - - if (argc > 3) { - username = (char *)JS_ToCString(ctx, argv[3]); - } - if (argc > 4) { - password = (char *)JS_ToCString(ctx, argv[4]); - } - if (username || password) { - if (username) { - x->uri->user = username; - x->uri->userlen = strlen(username); - } - if (password) { - x->uri->password = password; - x->uri->passwordlen = strlen(password); - } - } - char *url2 = get_uri_string(x->uri, URI_DIR_LOCATION | URI_PATH | URI_USER | URI_PASSWORD); - - if (username) { - JS_FreeCString(ctx, username); - } - if (password) { - JS_FreeCString(ctx, password); - } - - if (!url2) { - return JS_UNDEFINED; - } - done_uri(x->uri); - x->uri = get_uri(url2, URI_DIR_LOCATION | URI_PATH | URI_USER | URI_PASSWORD); - mem_free(url2); - - x->requestHeaders.clear(); - x->responseHeaders.clear(); - - x->ready_state = XHR_RSTATE_OPENED; - register_bottom_half(onreadystatechange_run, x); - } - return JS_UNDEFINED; -} - -static JSValue -xhr_overridemimetype(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_ThrowTypeError(ctx, "unsupported"); -} - -static size_t -write_data(void *ptr, size_t size, size_t nmemb, void *stream) -{ - Xhr *x = (Xhr *)stream; - size_t length = x->response_length; - - char *n = (char *)mem_realloc(x->response_text, length + size * nmemb + 1); - - if (n) { - x->response_text = n; - } else { - return 0; - } - memcpy(x->response_text + length, ptr, (size * nmemb)); - x->response_text[length + size * nmemb] = '\0'; - x->response_length += size * nmemb; - - return nmemb; -} - -static JSValue -xhr_send(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - Xhr *x = xhr_get(ctx, this_val); - - if (!x) { - return JS_EXCEPTION; - } - - if (!x->sent) { - JSValue arg = argv[0]; - - if (x->async && x->method == POST && JS_IsString(arg)) { - size_t size; - const char *body = JS_ToCStringLen(ctx, &size, arg); - - if (body) { - struct string post; - if (!init_string(&post)) { - JS_FreeCString(ctx, body); - return JS_EXCEPTION; - } - - add_to_string(&post, "text/plain\n"); - for (int i = 0; body[i]; i++) { - char p[3]; - - ulonghexcat(p, NULL, (int)body[i], 2, '0', 0); - add_to_string(&post, p); - } - x->uri->post = post.source; - char *url2 = get_uri_string(x->uri, URI_DIR_LOCATION | URI_PATH | URI_USER | URI_PASSWORD | URI_POST); - done_string(&post); - - if (!url2) { - JS_FreeCString(ctx, body); - return JS_EXCEPTION; - } - done_uri(x->uri); - x->uri = get_uri(url2, URI_DIR_LOCATION | URI_PATH | URI_USER | URI_PASSWORD | URI_POST); - mem_free(url2); - JS_FreeCString(ctx, body); - } - } - - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - struct view_state *vs = interpreter->vs; - struct document_view *doc_view = vs->doc_view; - - if (x->uri) { - if (x->uri->protocol == PROTOCOL_FILE && !get_opt_bool("ecmascript.allow_xhr_file", NULL)) { - return JS_UNDEFINED; - } - - if (!x->async) { - char *url = get_uri_string(x->uri, URI_DIR_LOCATION | URI_PATH | URI_USER | URI_PASSWORD); - - if (!url) { - return JS_UNDEFINED; - } - - x->sent = true; - /* init the curl session */ - CURL *curl_handle = curl_easy_init(); - /* set URL to get here */ - curl_easy_setopt(curl_handle, CURLOPT_URL, url); - curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 0L); - /* disable progress meter, set to 0L to enable it */ - curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L); - /* send all data to this function */ - curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data); - /* write the page body to this file handle */ - curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, x); - - JSValue arg = argv[0]; - if (JS_IsString(arg)) { - size_t size; - const char *body = JS_ToCStringLen(ctx, &size, arg); - - if (body) { - curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, (long) size); - curl_easy_setopt(curl_handle, CURLOPT_COPYPOSTFIELDS, body); - - JS_FreeCString(ctx, body); - } - } - - /* get it! */ - curl_easy_perform(curl_handle); - /* cleanup curl stuff */ - curl_easy_cleanup(curl_handle); - x->ready_state = XHR_RSTATE_DONE; - x->status = 200; - mem_free(url); - return JS_UNDEFINED; - } - x->sent = true; - x->download.data = x; - x->download.callback = (download_callback_T *)x_loading_callback; - load_uri(x->uri, doc_view->session->referrer, &x->download, PRI_MAIN, CACHE_MODE_NORMAL, -1); - if (x->timeout) { - set_connection_timeout_xhr(x->download.conn, x->timeout); - } - } - } - - return JS_UNDEFINED; -} - -static JSValue -xhr_setrequestheader(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - REF_JS(this_val); - - Xhr *x = xhr_get(ctx, this_val); - - if (!x) { - return JS_EXCEPTION; - } - - if (!JS_IsString(argv[0])) { - return JS_UNDEFINED; - } - const char *h_name, *h_value = NULL; - h_name = JS_ToCString(ctx, argv[0]); - - if (!h_name) { - return JS_UNDEFINED; - } - - if (!JS_IsUndefined(argv[1])) { - h_value = JS_ToCString(ctx, argv[1]); - } - - if (h_value) { - char *copy = stracpy(h_value); - - if (!copy) { - JS_FreeCString(ctx, h_name); - JS_FreeCString(ctx, h_value); - return JS_EXCEPTION; - } - char *normalized_value = normalize(copy); - - if (!valid_header(h_name)) { - JS_FreeCString(ctx, h_name); - JS_FreeCString(ctx, h_value); - return JS_UNDEFINED; - } - - if (forbidden_header(h_name)) { - JS_FreeCString(ctx, h_name); - JS_FreeCString(ctx, h_value); - return JS_UNDEFINED; - } - - bool found = false; - for (auto h: x->requestHeaders) { - const std::string hh = h.first; - if (!strcasecmp(hh.c_str(), h_name)) { - x->requestHeaders[hh] = x->requestHeaders[hh] + ", " + normalized_value; - found = true; - break; - } - } - - if (!found) { - x->requestHeaders[h_name] = normalized_value; - } - JS_FreeCString(ctx, h_value); - mem_free(copy); - } - JS_FreeCString(ctx, h_name); - - return JS_UNDEFINED; -} - -static const JSCFunctionListEntry xhr_class_funcs[] = { - JS_PROP_INT32_DEF("UNSENT", XHR_RSTATE_UNSENT, JS_PROP_ENUMERABLE), - JS_PROP_INT32_DEF("OPENED", XHR_RSTATE_OPENED, JS_PROP_ENUMERABLE), - JS_PROP_INT32_DEF("HEADERS_RECEIVED", XHR_RSTATE_HEADERS_RECEIVED, JS_PROP_ENUMERABLE), - JS_PROP_INT32_DEF("LOADING", XHR_RSTATE_LOADING, JS_PROP_ENUMERABLE), - JS_PROP_INT32_DEF("DONE", XHR_RSTATE_DONE, JS_PROP_ENUMERABLE), -}; - -static const JSCFunctionListEntry xhr_proto_funcs[] = { - JS_CGETSET_MAGIC_DEF("onabort", xhr_event_get, xhr_event_set, XHR_EVENT_ABORT), - JS_CGETSET_MAGIC_DEF("onerror", xhr_event_get, xhr_event_set, XHR_EVENT_ERROR), - JS_CGETSET_MAGIC_DEF("onload", xhr_event_get, xhr_event_set, XHR_EVENT_LOAD), - JS_CGETSET_MAGIC_DEF("onloadend", xhr_event_get, xhr_event_set, XHR_EVENT_LOAD_END), - JS_CGETSET_MAGIC_DEF("onloadstart", xhr_event_get, xhr_event_set, XHR_EVENT_LOAD_START), - JS_CGETSET_MAGIC_DEF("onprogress", xhr_event_get, xhr_event_set, XHR_EVENT_PROGRESS), - JS_CGETSET_MAGIC_DEF("onreadystatechange", xhr_event_get, xhr_event_set, XHR_EVENT_READY_STATE_CHANGED), - JS_CGETSET_MAGIC_DEF("ontimeout", xhr_event_get, xhr_event_set, XHR_EVENT_TIMEOUT), - JS_CGETSET_DEF("readyState", xhr_readystate_get, NULL), - JS_CGETSET_DEF("response", xhr_response_get, NULL), - JS_CGETSET_DEF("responseText", xhr_responsetext_get, NULL), - JS_CGETSET_DEF("responseType", xhr_responsetype_get, xhr_responsetype_set), - JS_CGETSET_DEF("responseURL", xhr_responseurl_get, NULL), - JS_CGETSET_DEF("status", xhr_status_get, NULL), - JS_CGETSET_DEF("statusText", xhr_statustext_get, NULL), - JS_CGETSET_DEF("timeout", xhr_timeout_get, xhr_timeout_set), - JS_CGETSET_DEF("upload", xhr_upload_get, NULL), - JS_CGETSET_DEF("withCredentials", xhr_withcredentials_get, xhr_withcredentials_set), - JS_CFUNC_DEF("abort", 0, xhr_abort), - JS_CFUNC_DEF("addEventListener", 3, xhr_addEventListener), - JS_CFUNC_DEF("getAllResponseHeaders", 0, xhr_getallresponseheaders), - JS_CFUNC_DEF("getResponseHeader", 1, xhr_getresponseheader), - JS_CFUNC_DEF("open", 5, xhr_open), - JS_CFUNC_DEF("overrideMimeType", 1, xhr_overridemimetype), - JS_CFUNC_DEF("removeEventListener", 3, xhr_removeEventListener), - JS_CFUNC_DEF("send", 1, xhr_send), - JS_CFUNC_DEF("setRequestHeader", 2, xhr_setrequestheader), -}; - -static void -JS_NewGlobalCConstructor2(JSContext *ctx, JSValue func_obj, const char *name, JSValueConst proto) -{ - REF_JS(func_obj); - REF_JS(proto); - - JSValue global_object = JS_GetGlobalObject(ctx); - - JS_DefinePropertyValueStr(ctx, global_object, name, - JS_DupValue(ctx, func_obj), JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); - JS_SetConstructor(ctx, func_obj, proto); - JS_FreeValue(ctx, func_obj); - JS_FreeValue(ctx, global_object); -} - -static JSValueConst -JS_NewGlobalCConstructor(JSContext *ctx, const char *name, JSCFunction *func, int length, JSValueConst proto) -{ - JSValue func_obj; - func_obj = JS_NewCFunction2(ctx, func, name, length, JS_CFUNC_constructor_or_func, 0); - REF_JS(func_obj); - REF_JS(proto); - - JS_NewGlobalCConstructor2(ctx, func_obj, name, proto); - - return func_obj; -} - -int -js_xhr_init(JSContext *ctx) -{ -#ifdef ECMASCRIPT_DEBUG - fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); -#endif - JSValue proto, obj; - - /* XHR class */ - JS_NewClassID(&xhr_class_id); - JS_NewClass(JS_GetRuntime(ctx), xhr_class_id, &xhr_class); - proto = JS_NewObject(ctx); - REF_JS(proto); - - JS_SetPropertyFunctionList(ctx, proto, xhr_proto_funcs, countof(xhr_proto_funcs)); - JS_SetClassProto(ctx, xhr_class_id, proto); - - /* XHR object */ - obj = JS_NewGlobalCConstructor(ctx, "XMLHttpRequest", xhr_constructor, 1, proto); - REF_JS(obj); - - JS_SetPropertyFunctionList(ctx, obj, xhr_class_funcs, countof(xhr_class_funcs)); - - return 0; -} -#endif