diff --git a/src/ecmascript/libdom/quickjs/Makefile b/src/ecmascript/libdom/quickjs/Makefile index 100ef181..88b79b50 100644 --- a/src/ecmascript/libdom/quickjs/Makefile +++ b/src/ecmascript/libdom/quickjs/Makefile @@ -1,6 +1,6 @@ top_builddir=../../../.. include $(top_builddir)/Makefile.config -OBJS = attr.o attributes.o collection.o console.o heartbeat.o history.o keyboard.o localstorage.o mapa.obj message.o navigator.o nodelist.o screen.o unibar.o +OBJS = attr.o attributes.o collection.o console.o heartbeat.o history.o keyboard.o localstorage.o location.o mapa.obj message.o navigator.o nodelist.o screen.o unibar.o include $(top_srcdir)/Makefile.lib diff --git a/src/ecmascript/libdom/quickjs/location.c b/src/ecmascript/libdom/quickjs/location.c new file mode 100644 index 00000000..60627041 --- /dev/null +++ b/src/ecmascript/libdom/quickjs/location.c @@ -0,0 +1,649 @@ +/* The QuickJS location object implementation. */ + +#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/location.h" +#include "protocol/uri.h" +#include "viewer/text/vs.h" + +#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, NULL), + 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); +} diff --git a/src/ecmascript/libdom/quickjs/meson.build b/src/ecmascript/libdom/quickjs/meson.build index d6d54993..6b296aa6 100644 --- a/src/ecmascript/libdom/quickjs/meson.build +++ b/src/ecmascript/libdom/quickjs/meson.build @@ -1 +1 @@ -srcs += files('attr.c', 'attributes.c', 'collection.c', 'console.c', 'heartbeat.c', 'history.c', 'keyboard.c', 'localstorage.c', 'mapa.cpp', 'message.c', 'navigator.c', 'nodelist.c', 'screen.c', 'unibar.c') +srcs += files('attr.c', 'attributes.c', 'collection.c', 'console.c', 'heartbeat.c', 'history.c', 'keyboard.c', 'localstorage.c', 'location.c', 'mapa.cpp', 'message.c', 'navigator.c', 'nodelist.c', 'screen.c', 'unibar.c') diff --git a/src/ecmascript/quickjs/location.cpp b/src/ecmascript/quickjs/location.cpp index d885e0a5..b727f5bf 100644 --- a/src/ecmascript/quickjs/location.cpp +++ b/src/ecmascript/quickjs/location.cpp @@ -43,6 +43,8 @@ #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; @@ -674,3 +676,4 @@ js_location_init(JSContext *ctx) RETURN_JS(location_proto); } +#endif diff --git a/src/ecmascript/quickjs/location.h b/src/ecmascript/quickjs/location.h index 13ac42a3..840361d1 100644 --- a/src/ecmascript/quickjs/location.h +++ b/src/ecmascript/quickjs/location.h @@ -3,6 +3,14 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + JSValue js_location_init(JSContext *ctx); +#ifdef __cplusplus +} +#endif + #endif