diff --git a/src/ecmascript/spidermonkey/element.c b/src/ecmascript/spidermonkey/element.c index 9a65a7450..98bdec3ba 100644 --- a/src/ecmascript/spidermonkey/element.c +++ b/src/ecmascript/spidermonkey/element.c @@ -1066,17 +1066,82 @@ element_set_property_title(JSContext *ctx, unsigned int argc, JS::Value *vp) return true; } +static bool element_contains(JSContext *ctx, unsigned int argc, JS::Value *rval); static bool element_getAttributeNode(JSContext *ctx, unsigned int argc, JS::Value *rval); static bool element_hasAttribute(JSContext *ctx, unsigned int argc, JS::Value *rval); static bool element_hasAttributes(JSContext *ctx, unsigned int argc, JS::Value *rval); const spidermonkeyFunctionSpec element_funcs[] = { + { "contains", element_contains, 1 }, { "getAttributeNode", element_getAttributeNode, 1 }, { "hasAttribute", element_hasAttribute, 1 }, { "hasAttributes", element_hasAttributes, 0 }, { NULL } }; +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 bool +element_contains(JSContext *ctx, unsigned int argc, JS::Value *rval) +{ + JSCompartment *comp = js::GetContextCompartment(ctx); + + if (!comp || argc != 1) { + return false; + } + + JS::CallArgs args = CallArgsFromVp(argc, rval); + JS::RootedObject hobj(ctx, &args.thisv().toObject()); + + struct ecmascript_interpreter *interpreter = JS_GetCompartmentPrivate(comp); + + if (!JS_InstanceOf(ctx, hobj, &element_class, NULL)) + return false; + + xmlpp::Element *el = JS_GetPrivate(hobj); + + if (!el) { + args.rval().setBoolean(false); + return true; + } + + JS::RootedObject node(ctx, &args[0].toObject()); + + xmlpp::Element *el2 = JS_GetPrivate(node); + + if (!el2) { + args.rval().setBoolean(false); + return true; + } + + bool result_set = false; + bool result = false; + + check_contains(el, el2, &result_set, &result); + args.rval().setBoolean(result); + + return true; +} + static bool element_getAttributeNode(JSContext *ctx, unsigned int argc, JS::Value *rval) { diff --git a/test/ecmascript/contains.html b/test/ecmascript/contains.html new file mode 100644 index 000000000..b08d95816 --- /dev/null +++ b/test/ecmascript/contains.html @@ -0,0 +1,32 @@ + + +
+ + + + +I am a p element inside div, and I have a span element inside of me.
+Click the button to find out if the div element contains a span element.
+ + + + + + + + +