Hello,
I want to add Element.matches to "my" browser based on the netsurf code.
The idea is:
generate the css rule:
$selector {color:#123456}
then for the given node, check whether computed css color is #123456.
It even works, but subsequent calls to this function cause memory leaks, which
I don't know how to resolve.
Code of this function looks like this.
void *
el_match_selector(const char *selector, void *node)
{
struct string text;
css_error code;
size_t size;
uint32_t count;
css_stylesheet_params params;
css_stylesheet *sheet = NULL;
css_select_ctx *select_ctx = NULL;
css_select_results *style = NULL;
uint8_t color_type;
css_color color_shade;
css_media media = {
.type = CSS_MEDIA_SCREEN,
};
css_unit_ctx unit_len_ctx = {0};
unit_len_ctx.viewport_width = 800; // TODO
unit_len_ctx.viewport_height = 600; // TODO
unit_len_ctx.device_dpi = F_90; //device_dpi;
/** \todo Change nsoption font sizes to px. */
/// f_size = FDIV(FMUL(F_96, FDIV(INTTOFIX(nsoption_int(font_size)), F_10)), F_72);
/// f_min = FDIV(FMUL(F_96, FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)), F_72);
unsigned int f_size = FDIV(FMUL(F_96, FDIV(INTTOFIX(50), F_10)), F_72); // TODO
unsigned int f_min = FDIV(FMUL(F_96, FDIV(INTTOFIX(50), F_10)), F_72); // TODO
unit_len_ctx.font_size_default = f_size;
unit_len_ctx.font_size_minimum = f_min;
void *ret = NULL;
params.params_version = CSS_STYLESHEET_PARAMS_VERSION_1;
params.level = CSS_LEVEL_21;
params.charset = "UTF-8";
params.url = "foo";
params.title = "foo";
params.allow_quirks = false;
params.inline_style = false;
params.resolve = resolve_url_empty;
params.resolve_pw = NULL;
params.import = NULL;
params.import_pw = NULL;
params.color = NULL;
params.color_pw = NULL;
params.font = NULL;
params.font_pw = NULL;
if (!selector) {
return NULL;
}
if (!init_string(&text)) {
return NULL;
}
add_to_string(&text, selector);
add_to_string(&text, "{color:#123456}");
/* create a stylesheet */
code = css_stylesheet_create(¶ms, &sheet);
if (code != CSS_OK) {
goto empty;
}
code = css_stylesheet_append_data(sheet, (const uint8_t *) text.source, text.length);
if (code != CSS_OK && code != CSS_NEEDDATA) {
goto empty;
}
code = css_stylesheet_data_done(sheet);
if (code != CSS_OK) {
goto empty;
}
//code = css_stylesheet_size(sheet, &size);
/* prepare a selection context containing the stylesheet */
code = css_select_ctx_create(&select_ctx);
if (code != CSS_OK) {
goto empty;
}
code = css_select_ctx_append_sheet(select_ctx, sheet, CSS_ORIGIN_AUTHOR, NULL);
if (code != CSS_OK) {
goto empty;
}
// code = css_select_ctx_count_sheets(select_ctx, &count);
//
// if (code != CSS_OK) {
// goto empty;
// }
code = css_select_style(select_ctx, node, &unit_len_ctx, &media, NULL, &selection_handler, 0, &style);
if (code != CSS_OK) {
goto empty;
}
color_type = css_computed_color(style->styles[CSS_PSEUDO_ELEMENT_NONE], &color_shade);
if (color_type && color_shade == 0xff123456) {
ret = node;
}
empty:
if (style) {
css_select_results_destroy(style);
}
if (select_ctx) {
css_select_ctx_destroy(select_ctx);
}
if (sheet) {
css_stylesheet_destroy(sheet);
}
done_string(&text);
return ret;
}
css selection handler functions are copy of netsurf-3.11 code for CSS.
Here is output of valgrind --leak-check=full elinks -test 1 element.matches.html
==126177== Memcheck, a memory error detector
==126177== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==126177== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==126177== Command: elinks -test 1 element.matches.html
==126177== Parent PID: 1827
==126177==
==126182==
==126182== HEAP SUMMARY:
==126182== in use at exit: 2,837,840 bytes in 28,145 blocks
==126182== total heap usage: 70,221 allocs, 42,076 frees, 27,357,263 bytes allocated
==126182==
==126182== LEAK SUMMARY:
==126182== definitely lost: 0 bytes in 0 blocks
==126182== indirectly lost: 0 bytes in 0 blocks
==126182== possibly lost: 0 bytes in 0 blocks
==126182== still reachable: 2,837,840 bytes in 28,145 blocks
==126182== suppressed: 0 bytes in 0 blocks
==126182== Reachable blocks (those to which a pointer was found) are not shown.
==126182== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==126182==
==126182== For lists of detected and suppressed errors, rerun with: -s
==126182== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==126177==
==126177== HEAP SUMMARY:
==126177== in use at exit: 59,984 bytes in 109 blocks
==126177== total heap usage: 80,910 allocs, 80,801 frees, 33,543,836 bytes allocated
==126177==
==126177== 72 (56 direct, 16 indirect) bytes in 1 blocks are definitely lost in loss record 18 of 36
==126177== at 0x48455EF: calloc (vg_replace_malloc.c:1328)
==126177== by 0x54079D2: css__create_node_data (select.c:144)
==126177== by 0x54079D2: css_select__initialise_selection_state (select.c:1089)
==126177== by 0x54079D2: css_select_style (select.c:1273)
==126177== by 0x1D1C13: el_match_selector (css.c:2503)
==126177== by 0x1733EA: js_element_matches (element.c:3356)
==126177== by 0x29568A: js_call_c_function (quickjs.c:15913)
==126177== by 0x25CA0A: JS_CallInternal (quickjs.c:16108)
==126177== by 0x25CD84: JS_CallInternal (quickjs.c:16515)
==126177== by 0x26476F: JS_CallFree (quickjs.c:18581)
==126177== by 0x2D29AC: JS_EvalFunctionInternal (quickjs.c:34211)
==126177== by 0x2D3AD3: __JS_EvalInternal (quickjs.c:34346)
==126177== by 0x2CFA5C: JS_EvalInternal (quickjs.c:34364)
==126177== by 0x2CFA5C: JS_EvalThis (quickjs.c:34395)
==126177== by 0x2CFA5C: JS_Eval (quickjs.c:34403)
==126177== by 0x16423D: quickjs_eval (quickjs.c:409)
==126177==
==126177== LEAK SUMMARY:
==126177== definitely lost: 56 bytes in 1 blocks
==126177== indirectly lost: 16 bytes in 1 blocks
==126177== possibly lost: 0 bytes in 0 blocks
==126177== still reachable: 59,912 bytes in 107 blocks
==126177== suppressed: 0 bytes in 0 blocks
==126177== Reachable blocks (those to which a pointer was found) are not shown.
==126177== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==126177==
==126177== For lists of detected and suppressed errors, rerun with: -s
==126177== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
element.matches.html looks like this:
<li id="a" class="e">Philippine eagle</li>
<script type="text/javascript">
console.error('element.matches.html');
var bird = document.getElementById('a');
bird.matches('li');
bird.matches('li');
console.exit();
</script>
If I comment the second bird.matches, there is no leak, so I guess the "problem" is somewhere in releasing memory of libcss.
Line number of libcss might be different than in libcss-0.9.2, because some debug statement were added.
Sorry for spam, but you wrote to ask first, not to ask for ask.
How to get clean (no leak) output from valgrind? How to release libcss memory between calls of el_match_selector?
Or do you have an idea how to implement Element.matches simpler?
--
Regards,
Witold Filipczyk