diff --git a/src/ecmascript/spidermonkey/Makefile b/src/ecmascript/spidermonkey/Makefile index b132d602..f99400b8 100644 --- a/src/ecmascript/spidermonkey/Makefile +++ b/src/ecmascript/spidermonkey/Makefile @@ -2,7 +2,7 @@ top_builddir=../../.. include $(top_builddir)/Makefile.config INCLUDES += $(SPIDERMONKEY_CFLAGS) -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 \ +OBJS = attr.obj attributes.obj collection.obj console.obj css.obj document.obj element.obj form.obj forms.obj heartbeat.obj history.obj implementation.obj input.obj \ keyboard.obj localstorage.obj location.obj message.obj navigator.obj nodelist.obj screen.obj style.obj unibar.obj window.obj xhr.obj include $(top_srcdir)/Makefile.lib diff --git a/src/ecmascript/spidermonkey/css.cpp b/src/ecmascript/spidermonkey/css.cpp new file mode 100644 index 00000000..a5588df9 --- /dev/null +++ b/src/ecmascript/spidermonkey/css.cpp @@ -0,0 +1,268 @@ +/* The SpiderMonkey html CSSStyleDeclaration object implementation. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "elinks.h" + +#include "ecmascript/libdom/dom.h" + +#include "ecmascript/spidermonkey/util.h" +#include + +#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/libdom/corestrings.h" +#include "document/view.h" +#include "ecmascript/ecmascript.h" +#include "ecmascript/spidermonkey/css.h" +#include "ecmascript/spidermonkey/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 + + +static bool CSSStyleDeclaration_item(JSContext *ctx, unsigned int argc, JS::Value *rval); +static bool CSSStyleDeclaration_namedItem(JSContext *ctx, unsigned int argc, JS::Value *rval); +static bool CSSStyleDeclaration_item2(JSContext *ctx, JS::HandleObject hobj, int index, JS::MutableHandleValue hvp); +static bool CSSStyleDeclaration_namedItem2(JSContext *ctx, JS::HandleObject hobj, char *str, JS::MutableHandleValue hvp); + +static void CSSStyleDeclaration_finalize(JS::GCContext *op, JSObject *obj) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif +} + +JSClassOps CSSStyleDeclaration_ops = { + nullptr, // addProperty + nullptr, // deleteProperty + nullptr, // enumerate + nullptr, // newEnumerate + nullptr, // resolve + nullptr, // mayResolve + CSSStyleDeclaration_finalize, // finalize + nullptr, // call + nullptr, // construct + JS_GlobalObjectTraceHook +}; + +JSClass CSSStyleDeclaration_class = { + "CSSStyleDeclaration", + JSCLASS_HAS_RESERVED_SLOTS(1), + &CSSStyleDeclaration_ops +}; + +static const spidermonkeyFunctionSpec CSSStyleDeclaration_funcs[] = { + { "item", CSSStyleDeclaration_item, 1 }, + { "namedItem", CSSStyleDeclaration_namedItem, 1 }, + { NULL } +}; + +static bool CSSStyleDeclaration_get_property_length(JSContext *ctx, unsigned int argc, JS::Value *vp); + +static JSPropertySpec CSSStyleDeclaration_props[] = { + JS_PSG("length", CSSStyleDeclaration_get_property_length, JSPROP_ENUMERATE), + JS_PS_END +}; + +static bool +CSSStyleDeclaration_get_property_length(JSContext *ctx, unsigned int argc, JS::Value *vp) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + JS::CallArgs args = CallArgsFromVp(argc, vp); + JS::RootedObject hobj(ctx, &args.thisv().toObject()); + + struct view_state *vs; + JS::Realm *comp = js::GetContextRealm(ctx); + + if (!comp) { +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); +#endif + return false; + } + args.rval().setInt32(3); // fake + + return true; +} + +static bool +CSSStyleDeclaration_item(JSContext *ctx, unsigned int argc, JS::Value *vp) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + JS::Value val; + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + JS::RootedObject hobj(ctx, &args.thisv().toObject()); + JS::RootedValue rval(ctx, val); + + int index = args[0].toInt32(); + bool ret = CSSStyleDeclaration_item2(ctx, hobj, index, &rval); + args.rval().set(rval); + + return ret; +} + +static bool +CSSStyleDeclaration_namedItem(JSContext *ctx, unsigned int argc, JS::Value *vp) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + JS::Value val; + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); + JS::RootedObject hobj(ctx, &args.thisv().toObject()); + JS::RootedValue rval(ctx, val); + + char *str = jsval_to_string(ctx, args[0]); + rval.setNull(); + bool ret = CSSStyleDeclaration_namedItem2(ctx, hobj, str, &rval); + args.rval().set(rval); + + mem_free_if(str); + + return ret; +} + +static bool +CSSStyleDeclaration_item2(JSContext *ctx, JS::HandleObject hobj, int idx, JS::MutableHandleValue hvp) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + JS::Realm *comp = js::GetContextRealm(ctx); + + if (!comp) { +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); +#endif + return false; + } + + if (!JS_InstanceOf(ctx, hobj, &CSSStyleDeclaration_class, NULL)) { +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); +#endif + return false; + } + hvp.setString(JS_NewStringCopyZ(ctx, "0")); // fake + + return true; +} + +static bool +CSSStyleDeclaration_namedItem2(JSContext *ctx, JS::HandleObject hobj, char *str, JS::MutableHandleValue hvp) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + JS::Realm *comp = js::GetContextRealm(ctx); + + if (!comp) { +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); +#endif + return false; + } + + if (!JS_InstanceOf(ctx, hobj, &CSSStyleDeclaration_class, NULL)) { +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); +#endif + return false; + } + hvp.setString(JS_NewStringCopyZ(ctx, "0")); // fake + + return true; +} + +static bool +CSSStyleDeclaration_set_items(JSContext *ctx, JS::HandleObject hobj, void *node) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + + JS::Realm *comp = js::GetContextRealm(ctx); + + if (!comp) { +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); +#endif + return false; + } + + /* This can be called if @obj if not itself an instance of the + * appropriate class but has one in its prototype chain. Fail + * such calls. */ + if (!JS_InstanceOf(ctx, hobj, &CSSStyleDeclaration_class, NULL)) { +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); +#endif + return false; + } + JS::RootedString zero(ctx, JS_NewStringCopyZ(ctx, "0")); + JS_DefineProperty(ctx, hobj, "marginTop", zero, JSPROP_ENUMERATE); + JS_DefineProperty(ctx, hobj, "marginLeft", zero, JSPROP_ENUMERATE); + JS_DefineProperty(ctx, hobj, "marginRight", zero, JSPROP_ENUMERATE); + + return true; +} + +JSObject * +getCSSStyleDeclaration(JSContext *ctx, void *node) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + JSObject *el = JS_NewObject(ctx, &CSSStyleDeclaration_class); + + if (!el) { + return NULL; + } + + JS::RootedObject r_el(ctx, el); + + JS_DefineProperties(ctx, r_el, (JSPropertySpec *) CSSStyleDeclaration_props); + spidermonkey_DefineFunctions(ctx, el, CSSStyleDeclaration_funcs); + + JS::SetReservedSlot(el, 0, JS::PrivateValue(node)); + CSSStyleDeclaration_set_items(ctx, r_el, node); + + return el; +} diff --git a/src/ecmascript/spidermonkey/css.h b/src/ecmascript/spidermonkey/css.h new file mode 100644 index 00000000..60be7ab2 --- /dev/null +++ b/src/ecmascript/spidermonkey/css.h @@ -0,0 +1,8 @@ +#ifndef EL__ECMASCRIPT_SPIDERMONKEY_CSS_H +#define EL__ECMASCRIPT_SPIDERMONKEY_CSS_H + +#include "ecmascript/spidermonkey/util.h" + +JSObject *getCSSStyleDeclaration(JSContext *ctx, void *node); + +#endif diff --git a/src/ecmascript/spidermonkey/meson.build b/src/ecmascript/spidermonkey/meson.build index bddea675..5fe14e94 100644 --- a/src/ecmascript/spidermonkey/meson.build +++ b/src/ecmascript/spidermonkey/meson.build @@ -1,2 +1,2 @@ -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', +srcs += files('attr.cpp', 'attributes.cpp', 'collection.cpp', 'console.cpp', 'css.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', 'style.cpp', 'unibar.cpp', 'window.cpp', 'xhr.cpp') diff --git a/src/ecmascript/spidermonkey/window.cpp b/src/ecmascript/spidermonkey/window.cpp index 1073715b..58587397 100644 --- a/src/ecmascript/spidermonkey/window.cpp +++ b/src/ecmascript/spidermonkey/window.cpp @@ -10,6 +10,8 @@ #include "elinks.h" +#include "ecmascript/libdom/dom.h" + #include "ecmascript/spidermonkey/util.h" #include #include @@ -24,6 +26,7 @@ #include "document/forms.h" #include "document/view.h" #include "ecmascript/ecmascript.h" +#include "ecmascript/spidermonkey/css.h" #include "ecmascript/spidermonkey/heartbeat.h" #include "ecmascript/spidermonkey/keyboard.h" #include "ecmascript/spidermonkey/location.h" @@ -169,6 +172,7 @@ void location_goto(struct document_view *doc_view, char *url); static bool window_addEventListener(JSContext *ctx, unsigned int argc, JS::Value *rval); static bool window_alert(JSContext *ctx, unsigned int argc, JS::Value *rval); static bool window_clearTimeout(JSContext *ctx, unsigned int argc, JS::Value *rval); +static bool window_getComputedStyle(JSContext *ctx, unsigned int argc, JS::Value *rval); static bool window_open(JSContext *ctx, unsigned int argc, JS::Value *rval); static bool window_postMessage(JSContext *ctx, unsigned int argc, JS::Value *rval); static bool window_removeEventListener(JSContext *ctx, unsigned int argc, JS::Value *rval); @@ -178,6 +182,7 @@ const spidermonkeyFunctionSpec window_funcs[] = { { "addEventListener", window_addEventListener, 3 }, { "alert", window_alert, 1 }, { "clearTimeout", window_clearTimeout, 1 }, + { "getComputedStyle", window_getComputedStyle, 2 }, { "open", window_open, 3 }, { "postMessage", window_postMessage, 3 }, { "removeEventListener", window_removeEventListener, 3 }, @@ -645,6 +650,35 @@ window_clearTimeout(JSContext *ctx, unsigned int argc, JS::Value *rval) return true; } +/* @window_funcs{"getComputedStyle"} */ +static bool +window_getComputedStyle(JSContext *ctx, unsigned int argc, JS::Value *rval) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + JS::Realm *comp = js::GetContextRealm(ctx); + + if (!comp) { +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); +#endif + return false; + } + if (argc < 1) { + return true; + } + + JS::CallArgs args = JS::CallArgsFromVp(argc, rval); + JS::RootedObject node(ctx, &args[0].toObject()); + dom_node *el = (dom_node *)JS::GetMaybePtrFromReservedSlot(node, 0); + JSObject *css = getCSSStyleDeclaration(ctx, el); + args.rval().setObject(*css); + + return true; +} + + #if 0 static bool window_get_property_closed(JSContext *ctx, JS::HandleObject hobj, JS::HandleId hid, JS::MutableHandleValue hvp)