From a9c89c0f6ceb5deb35df3a96bf710e756725b511 Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Sat, 16 Nov 2024 18:39:43 +0100 Subject: [PATCH] [spidermonkey] Image.width and Image.height in constructor --- src/js/spidermonkey/element.cpp | 125 ++++++++++++++++++++++++++++++++ src/js/spidermonkey/image.cpp | 34 +++++++++ test/js/assert/image.new.html | 5 +- 3 files changed, 162 insertions(+), 2 deletions(-) diff --git a/src/js/spidermonkey/element.cpp b/src/js/spidermonkey/element.cpp index a69eaa541..d014d529e 100644 --- a/src/js/spidermonkey/element.cpp +++ b/src/js/spidermonkey/element.cpp @@ -125,6 +125,8 @@ static bool element_get_property_title(JSContext *ctx, unsigned int argc, JS::Va static bool element_set_property_title(JSContext *ctx, unsigned int argc, JS::Value *vp); static bool element_get_property_value(JSContext *ctx, unsigned int argc, JS::Value *vp); static bool element_set_property_value(JSContext *ctx, unsigned int argc, JS::Value *vp); +static bool element_get_property_width(JSContext *ctx, unsigned int argc, JS::Value *vp); +static bool element_get_property_height(JSContext *ctx, unsigned int argc, JS::Value *vp); struct ele_listener { @@ -183,6 +185,7 @@ JSPropertySpec element_props[] = { JS_PSGS("dir", element_get_property_dir, element_set_property_dir, JSPROP_ENUMERATE), JS_PSG("firstChild", element_get_property_firstChild, JSPROP_ENUMERATE), JS_PSG("firstElementChild", element_get_property_firstElementChild, JSPROP_ENUMERATE), + JS_PSG("height", element_get_property_height, JSPROP_ENUMERATE), JS_PSGS("href", element_get_property_href, element_set_property_href, JSPROP_ENUMERATE), JS_PSGS("id", element_get_property_id, element_set_property_id, JSPROP_ENUMERATE), JS_PSGS("innerHTML", element_get_property_innerHtml, element_set_property_innerHtml, JSPROP_ENUMERATE), @@ -211,6 +214,7 @@ JSPropertySpec element_props[] = { JS_PSGS("textContent", element_get_property_textContent, element_set_property_textContent, JSPROP_ENUMERATE), JS_PSGS("title", element_get_property_title, element_set_property_title, JSPROP_ENUMERATE), JS_PSGS("value", element_get_property_value, element_set_property_value, JSPROP_ENUMERATE), + JS_PSG("width", element_get_property_width, JSPROP_ENUMERATE), JS_PS_END }; @@ -1145,6 +1149,66 @@ element_get_property_firstElementChild(JSContext *ctx, unsigned int argc, JS::Va return true; } +static bool +element_get_property_height(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; + } + + struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS::GetRealmPrivate(comp); + + /* 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, &element_class, NULL)) { +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); +#endif + return false; + } + + vs = interpreter->vs; + if (!vs) { +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); +#endif + return false; + } + + dom_node *el = (dom_node *)JS::GetMaybePtrFromReservedSlot(hobj, 0); + dom_string *h = NULL; + dom_exception exc; + + if (!el) { + args.rval().setNull(); + return true; + } + exc = dom_element_get_attribute(el, corestring_dom_height, &h); + + if (exc != DOM_NO_ERR || !h) { + args.rval().setInt32(0); + return true; + } + int height = atoi(dom_string_data(h)); + args.rval().setInt32(height); + dom_string_unref(h); + + return true; +} + static bool element_get_property_href(JSContext *ctx, unsigned int argc, JS::Value *vp) { @@ -2834,6 +2898,67 @@ element_get_property_textContent(JSContext *ctx, unsigned int argc, JS::Value *v return true; } +static bool +element_get_property_width(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; + } + + struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS::GetRealmPrivate(comp); + + /* 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, &element_class, NULL)) { +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); +#endif + return false; + } + + vs = interpreter->vs; + if (!vs) { +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s %d\n", __FILE__, __FUNCTION__, __LINE__); +#endif + return false; + } + + dom_node *el = (dom_node *)JS::GetMaybePtrFromReservedSlot(hobj, 0); + dom_string *w = NULL; + dom_exception exc; + + if (!el) { + args.rval().setNull(); + return true; + } + exc = dom_element_get_attribute(el, corestring_dom_width, &w); + + if (exc != DOM_NO_ERR || !w) { + args.rval().setInt32(0); + return true; + } + int width = atoi(dom_string_data(w)); + args.rval().setInt32(width); + dom_string_unref(w); + + return true; +} + + static bool element_set_property_checked(JSContext *ctx, unsigned int argc, JS::Value *vp) { diff --git a/src/js/spidermonkey/image.cpp b/src/js/spidermonkey/image.cpp index 1c30b6a6e..c7a6c81be 100644 --- a/src/js/spidermonkey/image.cpp +++ b/src/js/spidermonkey/image.cpp @@ -75,6 +75,40 @@ image_constructor(JSContext* ctx, unsigned argc, JS::Value* vp) args.rval().setNull(); return true; } + + if (argc > 0) { + char *width = jsval_to_string(ctx, args[0]); + + if (width) { + size_t width_len = strlen(width); + dom_string *value_str = NULL; + + exc = dom_string_create((const uint8_t *)width, width_len, &value_str); + mem_free(width); + + if (exc == DOM_NO_ERR) { + (void)dom_element_set_attribute(element, corestring_dom_width, value_str); + dom_string_unref(value_str); + } + } + } + + if (argc > 1) { + char *height = jsval_to_string(ctx, args[1]); + + if (height) { + size_t height_len = strlen(height); + dom_string *value_str = NULL; + + exc = dom_string_create((const uint8_t *)height, height_len, &value_str); + mem_free(height); + + if (exc == DOM_NO_ERR) { + (void)dom_element_set_attribute(element, corestring_dom_height, value_str); + dom_string_unref(value_str); + } + } + } JSObject *obj = getNode(ctx, element); args.rval().setObject(*obj); diff --git a/test/js/assert/image.new.html b/test/js/assert/image.new.html index 9118095e0..c54c16e3b 100644 --- a/test/js/assert/image.new.html +++ b/test/js/assert/image.new.html @@ -7,10 +7,11 @@ function myFunction() { var image = new Image; console.assert(image.nodeType === 1, 'Image type 1'); console.assert(image.tagName === 'IMG', 'IMG'); + console.assert(!image.width, image.width); var im2 = new Image(100, 200); - console.assert(im2.width === 100, 'width 100'); - console.assert(im2.height === 200, 'height 200'); + console.assert(im2.width === 100, im2.width); + console.assert(im2.height === 200, im2.height); } console.error('image.new.html'); myFunction();