From 3daca597b5cb7fe1738df7383023f753f05026dc Mon Sep 17 00:00:00 2001 From: Witold Filipczyk Date: Tue, 25 Jun 2024 18:25:52 +0200 Subject: [PATCH] [quickjs] document.getElementsByClassName Need to free strings. --- src/ecmascript/ecmascript-c.c | 6 ++-- src/ecmascript/quickjs/collection.c | 40 +++++++++++++++++---- src/ecmascript/quickjs/document.c | 56 ++++++++++------------------- 3 files changed, 55 insertions(+), 47 deletions(-) diff --git a/src/ecmascript/ecmascript-c.c b/src/ecmascript/ecmascript-c.c index 8af5467a..fcd6c91a 100644 --- a/src/ecmascript/ecmascript-c.c +++ b/src/ecmascript/ecmascript-c.c @@ -728,9 +728,9 @@ el_dom_html_collection_create(dom_html_document *doc, dom_node *root, dom_callback_is_in_collection ic, void *ctx, - el_dom_html_collection **col) + struct el_dom_html_collection **col) { - *col = (el_dom_html_collection *)malloc(sizeof(struct el_dom_html_collection)); + *col = (struct el_dom_html_collection *)malloc(sizeof(struct el_dom_html_collection)); if (*col == NULL) { return DOM_NO_MEM_ERR; @@ -750,7 +750,7 @@ get_elements_by_class_name(dom_html_document *doc, dom_node *node, char *classes if (!list) { return NULL; } - el_dom_html_collection *col = NULL; + struct el_dom_html_collection *col = NULL; dom_exception exc = el_dom_html_collection_create(doc, node, node_has_classes, list, &col); if (exc != DOM_NO_ERR || !col) { diff --git a/src/ecmascript/quickjs/collection.c b/src/ecmascript/quickjs/collection.c index d43ec56d..5278eb12 100644 --- a/src/ecmascript/quickjs/collection.c +++ b/src/ecmascript/quickjs/collection.c @@ -27,6 +27,8 @@ void *map_collections; void *map_rev_collections; +JSClassID js_htmlCollection_class_id; + static void * js_htmlCollection_GetOpaque(JSValueConst this_val) { @@ -47,6 +49,20 @@ js_htmlCollection_SetOpaque(JSValueConst this_val, void *node) } } +static +void js_htmlColection_finalizer(JSRuntime *rt, JSValue val) +{ +#ifdef ECMASCRIPT_DEBUG + fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); +#endif + REF_JS(val); + dom_html_collection *ns = (dom_html_collection *)(js_htmlCollection_GetOpaque(val)); + + if (ns) { + dom_html_collection_unref(ns); + } +} + static JSValue js_htmlCollection_get_property_length(JSContext *ctx, JSValueConst this_val) { @@ -292,6 +308,11 @@ static const JSCFunctionListEntry js_htmlCollection_proto_funcs[] = { JS_CFUNC_DEF("toString", 0, js_htmlCollection_toString) }; +static JSClassDef js_htmlCollection_class = { + "htmlCollection", + .finalizer = js_htmlColection_finalizer +}; + JSValue getCollection(JSContext *ctx, void *node) { @@ -311,12 +332,19 @@ getCollection(JSContext *ctx, void *node) 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); - attr_save_in_map(map_collections, node, htmlCollection_obj); - JSValue rr = JS_DupValue(ctx, htmlCollection_obj); + /* nodelist class */ + JS_NewClassID(&js_htmlCollection_class_id); + JS_NewClass(JS_GetRuntime(ctx), js_htmlCollection_class_id, &js_htmlCollection_class); + JSValue proto = JS_NewArray(ctx); + REF_JS(proto); + + JS_SetPropertyFunctionList(ctx, proto, js_htmlCollection_proto_funcs, countof(js_htmlCollection_proto_funcs)); + JS_SetClassProto(ctx, js_htmlCollection_class_id, proto); + + js_htmlCollection_SetOpaque(proto, node); + js_htmlCollection_set_items(ctx, proto, node); + attr_save_in_map(map_collections, node, proto); + JSValue rr = JS_DupValue(ctx, proto); RETURN_JS(rr); } diff --git a/src/ecmascript/quickjs/document.c b/src/ecmascript/quickjs/document.c index 6816f396..1419d26e 100644 --- a/src/ecmascript/quickjs/document.c +++ b/src/ecmascript/quickjs/document.c @@ -105,7 +105,6 @@ js_document_get_property_anchors(JSContext *ctx, JSValueConst this_val) return JS_NULL; } JSValue rr = getCollection(ctx, anchors); - JS_FreeValue(ctx, rr); dom_node_unref(doc); RETURN_JS(rr); @@ -509,7 +508,6 @@ js_document_get_property_images(JSContext *ctx, JSValueConst this_val) return JS_NULL; } JSValue rr = getCollection(ctx, images); - JS_FreeValue(ctx, rr); dom_node_unref(doc); RETURN_JS(rr); @@ -549,7 +547,6 @@ js_document_get_property_links(JSContext *ctx, JSValueConst this_val) return JS_NULL; } JSValue rr = getCollection(ctx, links); - JS_FreeValue(ctx, rr); dom_node_unref(doc); RETURN_JS(rr); @@ -1461,44 +1458,27 @@ js_document_getElementsByClassName(JSContext *ctx, JSValueConst this_val, int ar fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__); #endif REF_JS(this_val); + dom_html_document *doc = (struct dom_html_document *)js_doc_getopaque(this_val, js_document_class_id); - if (argc != 1) { - return JS_FALSE; - } - struct ecmascript_interpreter *interpreter = (struct ecmascript_interpreter *)JS_GetContextOpaque(ctx); - -// TODO - return JS_NULL; -#if 0 - - 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) { + if (!doc) { return JS_NULL; } - *elements = root->find(xpath); - JSValue rr = getCollection(ctx, elements); - JS_FreeValue(ctx, rr); - RETURN_JS(rr); -#endif + if (argc != 1) { + return JS_NULL; + } + const char *classes = JS_ToCString(ctx, argv[0]); + dom_html_collection *col = get_elements_by_class_name(doc, (dom_node *)doc, classes); + + if (classes) { + JS_FreeCString(ctx, classes); + } + if (!col) { + return JS_NULL; + } + JSValue ret = getCollection(ctx, col); + + RETURN_JS(ret); } static JSValue @@ -1853,7 +1833,7 @@ static const JSCFunctionListEntry js_document_proto_funcs[] = { JS_CFUNC_DEF("removeEventListener", 3, js_document_removeEventListener), 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("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),