1
0
mirror of https://github.com/rkd77/elinks.git synced 2025-01-03 14:57:44 -05:00

[quickjs] Workaround for memory leak in anchors

Check if refcnt is positive before unref node in element_finalizer.
refcnt was -1. Likely it is a bug in elinks code, but it is hard to locate it.
Also commented out ref|unref in element and document.
Collection code also changed. Array is not prototype for collection object.
This commit is contained in:
Witold Filipczyk 2024-07-22 18:33:56 +02:00
parent 95f45b7327
commit 7149746eb1
3 changed files with 342 additions and 334 deletions

View File

@ -34,7 +34,9 @@ js_htmlCollection_GetOpaque(JSValueConst this_val)
{
REF_JS(this_val);
return attr_find_in_map_rev(map_rev_collections, this_val);
return JS_GetOpaque(this_val, js_htmlCollection_class_id);
// return attr_find_in_map_rev(map_rev_collections, this_val);
}
static void
@ -42,11 +44,14 @@ js_htmlCollection_SetOpaque(JSValueConst this_val, void *node)
{
REF_JS(this_val);
JS_SetOpaque(this_val, node);
#if 0
if (!node) {
attr_erase_from_map_rev(map_rev_collections, this_val);
} else {
attr_save_in_map_rev(map_rev_collections, this_val, node);
}
#endif
}
static
@ -59,7 +64,7 @@ void js_htmlColection_finalizer(JSRuntime *rt, JSValue val)
dom_html_collection *ns = (dom_html_collection *)(js_htmlCollection_GetOpaque(val));
if (ns) {
attr_erase_from_map_str(map_collections, ns);
//attr_erase_from_map_str(map_collections, ns);
dom_html_collection_unref(ns);
}
}
@ -321,30 +326,30 @@ getCollection(JSContext *ctx, void *node)
fprintf(stderr, "%s:%s\n", __FILE__, __FUNCTION__);
#endif
static int initialized;
JSValue second;
// JSValue second;
if (!initialized) {
/* collection class */
JS_NewClassID(&js_htmlCollection_class_id);
JS_NewClass(JS_GetRuntime(ctx), js_htmlCollection_class_id, &js_htmlCollection_class);
initialized = 1;
}
second = attr_find_in_map(map_collections, node);
// second = attr_find_in_map(map_collections, node);
if (!JS_IsNull(second)) {
JSValue r = JS_DupValue(ctx, second);
RETURN_JS(r);
}
/* 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);
// if (!JS_IsNull(second)) {
// JSValue r = JS_DupValue(ctx, second);
//
// RETURN_JS(r);
// }
JSValue proto = JS_NewObjectClass(ctx, js_htmlCollection_class_id);
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);
// js_htmlCollection_set_items(ctx, proto, node);
// attr_save_in_map(map_collections, node, proto);
JSValue rr = JS_DupValue(ctx, proto);
RETURN_JS(rr);

View File

@ -114,16 +114,16 @@ js_document_get_property_anchors(JSContext *ctx, JSValueConst this_val)
if (!doc) {
return JS_NULL;
}
dom_node_ref(doc);
//dom_node_ref(doc);
dom_html_collection *anchors = NULL;
dom_exception exc = dom_html_document_get_anchors(doc, &anchors);
if (exc != DOM_NO_ERR || !anchors) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
JSValue rr = getCollection(ctx, anchors);
dom_node_unref(doc);
//dom_node_unref(doc);
RETURN_JS(rr);
}
@ -175,16 +175,16 @@ js_document_get_property_body(JSContext *ctx, JSValueConst this_val)
if (!doc) {
return JS_NULL;
}
dom_node_ref(doc);
//dom_node_ref(doc);
dom_html_element *body = NULL;
dom_exception exc = dom_html_document_get_body(doc, &body);
if (exc != DOM_NO_ERR || !body) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
dom_node_unref(doc);
//dom_node_unref(doc);
return getElement(ctx, body);
}
@ -305,13 +305,13 @@ js_document_get_property_childNodes(JSContext *ctx, JSValueConst this_val)
if (!doc) {
return JS_NULL;
}
dom_node_ref(doc);
//dom_node_ref(doc);
dom_element *root = NULL;
dom_exception exc = dom_document_get_document_element(doc, &root);
if (exc != DOM_NO_ERR || !root) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
dom_nodelist *nodes = NULL;
@ -319,10 +319,10 @@ js_document_get_property_childNodes(JSContext *ctx, JSValueConst this_val)
dom_node_unref(root);
if (exc != DOM_NO_ERR || !nodes) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
dom_node_unref(doc);
//dom_node_unref(doc);
return getNodeList(ctx, nodes);
}
@ -352,11 +352,11 @@ js_document_get_property_doctype(JSContext *ctx, JSValueConst this_val)
if (!doc) {
return JS_NULL;
}
dom_node_ref(doc);
//dom_node_ref(doc);
dom_document_type *dtd;
dom_document_get_doctype(doc, &dtd);
dom_node_unref(doc);
//dom_node_unref(doc);
return getDoctype(ctx, dtd);
}
@ -374,16 +374,16 @@ js_document_get_property_documentElement(JSContext *ctx, JSValueConst this_val)
if (!doc) {
return JS_NULL;
}
dom_node_ref(doc);
//dom_node_ref(doc);
dom_html_element *root = NULL;
dom_exception exc = dom_document_get_document_element(doc, &root);
if (exc != DOM_NO_ERR || !root) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
dom_node_unref(doc);
//dom_node_unref(doc);
return getElement(ctx, root);
}
@ -466,18 +466,18 @@ js_document_get_property_forms(JSContext *ctx, JSValueConst this_val)
if (!doc) {
return JS_NULL;
}
dom_node_ref(doc);
//dom_node_ref(doc);
dom_html_collection *forms = NULL;
dom_exception exc = dom_html_document_get_forms(doc, &forms);
if (exc != DOM_NO_ERR || !forms) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
JSValue rr = getForms(ctx, forms);
JS_FreeValue(ctx, rr);
dom_node_unref(doc);
//dom_node_unref(doc);
RETURN_JS(rr);
}
@ -509,17 +509,17 @@ js_document_get_property_images(JSContext *ctx, JSValueConst this_val)
if (!doc) {
return JS_NULL;
}
dom_node_ref(doc);
//dom_node_ref(doc);
dom_html_collection *images = NULL;
dom_exception exc = dom_html_document_get_images(doc, &images);
if (exc != DOM_NO_ERR || !images) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
JSValue rr = getCollection(ctx, images);
dom_node_unref(doc);
//dom_node_unref(doc);
RETURN_JS(rr);
}
@ -548,16 +548,16 @@ js_document_get_property_links(JSContext *ctx, JSValueConst this_val)
if (!doc) {
return JS_NULL;
}
dom_node_ref(doc);
//dom_node_ref(doc);
dom_html_collection *links = NULL;
dom_exception exc = dom_html_document_get_links(doc, &links);
if (exc != DOM_NO_ERR || !links) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
JSValue rr = getCollection(ctx, links);
dom_node_unref(doc);
//dom_node_unref(doc);
RETURN_JS(rr);
}
@ -1131,10 +1131,10 @@ js_document_dispatchEvent(JSContext *ctx, JSValueConst this_val, int argc, JSVal
if (!doc) {
return JS_FALSE;
}
dom_node_ref(doc);
//dom_node_ref(doc);
if (argc < 1) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_FALSE;
}
JSValue eve = argv[0];
@ -1149,7 +1149,7 @@ js_document_dispatchEvent(JSContext *ctx, JSValueConst this_val, int argc, JSVal
if (event) {
dom_event_unref(event);
}
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NewBool(ctx, result);
}
@ -1168,10 +1168,10 @@ js_document_removeEventListener(JSContext *ctx, JSValueConst this_val, int argc,
return JS_NULL;
}
dom_html_document *doc = (dom_html_document *)doc_private->node;
dom_node_ref(doc);
//dom_node_ref(doc);
if (argc < 2) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_UNDEFINED;
}
const char *str;
@ -1179,14 +1179,14 @@ js_document_removeEventListener(JSContext *ctx, JSValueConst this_val, int argc,
str = JS_ToCStringLen(ctx, &len, argv[0]);
if (!str) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_EXCEPTION;
}
char *method = stracpy(str);
JS_FreeCString(ctx, str);
if (!method) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_EXCEPTION;
}
JSValue fun = argv[1];
@ -1211,13 +1211,13 @@ js_document_removeEventListener(JSContext *ctx, JSValueConst this_val, int argc,
mem_free_set(&l->typ, NULL);
mem_free(l);
mem_free(method);
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_UNDEFINED;
}
}
mem_free(method);
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_UNDEFINED;
}
@ -1238,7 +1238,7 @@ js_document_createComment(JSContext *ctx, JSValueConst this_val, int argc, JSVal
if (!doc) {
return JS_NULL;
}
dom_node_ref(doc);
//dom_node_ref(doc);
dom_string *data = NULL;
dom_exception exc;
@ -1248,14 +1248,14 @@ js_document_createComment(JSContext *ctx, JSValueConst this_val, int argc, JSVal
str = JS_ToCStringLen(ctx, &len, argv[0]);
if (!str) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_EXCEPTION;
}
exc = dom_string_create((const uint8_t *)str, len, &data);
JS_FreeCString(ctx, str);
if (exc != DOM_NO_ERR || !data) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
dom_comment *comment = NULL;
@ -1263,10 +1263,10 @@ js_document_createComment(JSContext *ctx, JSValueConst this_val, int argc, JSVal
dom_string_unref(data);
if (exc != DOM_NO_ERR || !comment) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
dom_node_unref(doc);
//dom_node_unref(doc);
return getElement(ctx, comment);
}
@ -1287,16 +1287,16 @@ js_document_createDocumentFragment(JSContext *ctx, JSValueConst this_val, int ar
if (!doc) {
return JS_NULL;
}
dom_node_ref(doc);
//dom_node_ref(doc);
dom_document_fragment *fragment = NULL;
dom_exception exc = dom_document_create_document_fragment(doc, &fragment);
if (exc != DOM_NO_ERR || !fragment) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
dom_node_unref(doc);
//dom_node_unref(doc);
return getElement(ctx, fragment);
}
@ -1317,7 +1317,7 @@ js_document_createElement(JSContext *ctx, JSValueConst this_val, int argc, JSVal
if (!doc) {
return JS_NULL;
}
dom_node_ref(doc);
//dom_node_ref(doc);
dom_string *tag_name = NULL;
dom_exception exc;
@ -1327,14 +1327,14 @@ js_document_createElement(JSContext *ctx, JSValueConst this_val, int argc, JSVal
str = JS_ToCStringLen(ctx, &len, argv[0]);
if (!str) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_EXCEPTION;
}
exc = dom_string_create((const uint8_t *)str, len, &tag_name);
JS_FreeCString(ctx, str);
if (exc != DOM_NO_ERR || !tag_name) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
dom_element *element = NULL;
@ -1342,10 +1342,10 @@ js_document_createElement(JSContext *ctx, JSValueConst this_val, int argc, JSVal
dom_string_unref(tag_name);
if (exc != DOM_NO_ERR || !element) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
dom_node_unref(doc);
//dom_node_unref(doc);
return getElement(ctx, element);
}
@ -1366,7 +1366,7 @@ js_document_createTextNode(JSContext *ctx, JSValueConst this_val, int argc, JSVa
if (!doc) {
return JS_NULL;
}
dom_node_ref(doc);
//dom_node_ref(doc);
dom_string *data = NULL;
dom_exception exc;
@ -1376,14 +1376,14 @@ js_document_createTextNode(JSContext *ctx, JSValueConst this_val, int argc, JSVa
str = JS_ToCStringLen(ctx, &len, argv[0]);
if (!str) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_EXCEPTION;
}
exc = dom_string_create((const uint8_t *)str, len, &data);
JS_FreeCString(ctx, str);
if (exc != DOM_NO_ERR || !data) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
dom_text *text_node = NULL;
@ -1391,10 +1391,10 @@ js_document_createTextNode(JSContext *ctx, JSValueConst this_val, int argc, JSVa
dom_string_unref(data);
if (exc != DOM_NO_ERR || !text_node) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
dom_node_unref(doc);
//dom_node_unref(doc);
return getElement(ctx, text_node);
}
@ -1415,7 +1415,7 @@ js_document_getElementById(JSContext *ctx, JSValueConst this_val, int argc, JSVa
if (!doc) {
return JS_NULL;
}
dom_node_ref(doc);
//dom_node_ref(doc);
dom_string *id = NULL;
dom_exception exc;
@ -1425,14 +1425,14 @@ js_document_getElementById(JSContext *ctx, JSValueConst this_val, int argc, JSVa
str = JS_ToCStringLen(ctx, &len, argv[0]);
if (!str) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_EXCEPTION;
}
exc = dom_string_create((const uint8_t *)str, len, &id);
JS_FreeCString(ctx, str);
if (exc != DOM_NO_ERR || !id) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
dom_element *element = NULL;
@ -1440,10 +1440,10 @@ js_document_getElementById(JSContext *ctx, JSValueConst this_val, int argc, JSVa
dom_string_unref(id);
if (exc != DOM_NO_ERR || !element) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
dom_node_unref(doc);
//dom_node_unref(doc);
return getElement(ctx, element);
}
@ -1543,7 +1543,7 @@ js_document_getElementsByTagName(JSContext *ctx, JSValueConst this_val, int argc
if (!doc) {
return JS_NULL;
}
dom_node_ref(doc);
//dom_node_ref(doc);
dom_string *tagname = NULL;
dom_exception exc;
@ -1553,14 +1553,14 @@ js_document_getElementsByTagName(JSContext *ctx, JSValueConst this_val, int argc
str = JS_ToCStringLen(ctx, &len, argv[0]);
if (!str) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_EXCEPTION;
}
exc = dom_string_create((const uint8_t *)str, len, &tagname);
JS_FreeCString(ctx, str);
if (exc != DOM_NO_ERR || !tagname) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
dom_nodelist *nodes = NULL;
@ -1568,11 +1568,11 @@ js_document_getElementsByTagName(JSContext *ctx, JSValueConst this_val, int argc
dom_string_unref(tagname);
if (exc != DOM_NO_ERR || !nodes) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
JSValue rr = getNodeList(ctx, nodes);
dom_node_unref(doc);
//dom_node_unref(doc);
RETURN_JS(rr);
}
@ -1593,21 +1593,21 @@ js_document_querySelector(JSContext *ctx, JSValueConst this_val, int argc, JSVal
if (!doc) {
return JS_NULL;
}
dom_node_ref(doc);
//dom_node_ref(doc);
dom_node *root = NULL; /* root element of document */
/* Get root element */
dom_exception exc = dom_document_get_document_element(doc, &root);
if (exc != DOM_NO_ERR) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
size_t len;
const char *selector = JS_ToCStringLen(ctx, &len, argv[0]);
if (!selector) {
dom_node_unref(doc);
//dom_node_unref(doc);
dom_node_unref(root);
return JS_NULL;
}
@ -1616,10 +1616,10 @@ js_document_querySelector(JSContext *ctx, JSValueConst this_val, int argc, JSVal
dom_node_unref(root);
if (!ret) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
dom_node_unref(doc);
//dom_node_unref(doc);
return getElement(ctx, ret);
}
@ -1640,20 +1640,20 @@ js_document_querySelectorAll(JSContext *ctx, JSValueConst this_val, int argc, JS
if (!doc) {
return JS_NULL;
}
dom_node_ref(doc);
//dom_node_ref(doc);
dom_node *doc_root = NULL; /* root element of document */
/* Get root element */
dom_exception exc = dom_document_get_document_element(doc, &doc_root);
if (exc != DOM_NO_ERR) {
dom_node_unref(doc);
//dom_node_unref(doc);
return JS_NULL;
}
size_t len;
const char *selector = JS_ToCStringLen(ctx, &len, argv[0]);
if (!selector) {
dom_node_unref(doc);
//dom_node_unref(doc);
dom_node_unref(doc_root);
return JS_NULL;
}
@ -1662,7 +1662,7 @@ js_document_querySelectorAll(JSContext *ctx, JSValueConst this_val, int argc, JS
exc = dom_string_create((const uint8_t *)"B", 1, &tag_name);
if (exc != DOM_NO_ERR || !tag_name) {
dom_node_unref(doc);
//dom_node_unref(doc);
dom_node_unref(doc_root);
JS_FreeCString(ctx, selector);
return JS_NULL;
@ -1672,7 +1672,7 @@ js_document_querySelectorAll(JSContext *ctx, JSValueConst this_val, int argc, JS
dom_string_unref(tag_name);
if (exc != DOM_NO_ERR || !element) {
dom_node_unref(doc);
//dom_node_unref(doc);
dom_node_unref(doc_root);
JS_FreeCString(ctx, selector);
return JS_NULL;
@ -1680,7 +1680,7 @@ js_document_querySelectorAll(JSContext *ctx, JSValueConst this_val, int argc, JS
LIST_OF(struct selector_node) *result_list = (LIST_OF(struct selector_node) *)mem_calloc(1, sizeof(*result_list));
if (!result_list) {
dom_node_unref(doc);
//dom_node_unref(doc);
dom_node_unref(doc_root);
JS_FreeCString(ctx, selector);
return JS_NULL;
@ -1690,7 +1690,7 @@ js_document_querySelectorAll(JSContext *ctx, JSValueConst this_val, int argc, JS
walk_tree_query_append((dom_node *)element, doc_root, selector, 0, result_list);
dom_node_unref(doc_root);
JS_FreeCString(ctx, selector);
dom_node_unref(doc);
//dom_node_unref(doc);
return getNodeList2(ctx, result_list);
}

File diff suppressed because it is too large Load Diff