1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-06-15 23:35:34 +00:00

[spidermonkey] document.querySelector

It passes test case.
This commit is contained in:
Witold Filipczyk 2024-05-05 16:58:10 +02:00
parent be67094940
commit cc718c30b5
4 changed files with 208 additions and 3 deletions

View File

@ -97,7 +97,11 @@ static css_error node_presentational_hint(void *pw, void *node,
return CSS_OK;
}
static css_error
resolve_url_empty(void *pw, const char *base, lwc_string *rel, lwc_string **abs)
{
return CSS_OK;
}
css_error
resolve_url(void *pw, const char *base, lwc_string *rel, lwc_string **abs)
@ -2309,3 +2313,122 @@ import_css2(struct html_context *html_context, struct uri *uri)
// css->import_level--;
}
}
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(&params, &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;
}

View File

@ -11,6 +11,7 @@ struct string;
void *document_parse_text(const char *charset, char *data, size_t length);
void *document_parse(struct document *document, struct string *source);
void free_document(void *doc);
void *el_match_selector(const char *selector, void *node);
#ifdef __cplusplus
}

View File

@ -1819,6 +1819,62 @@ document_getElementsByTagName(JSContext *ctx, unsigned int argc, JS::Value *vp)
return true;
}
void *
walk_tree_query(dom_node *node, char *selector, int depth)
{
dom_exception exc;
dom_node *child;
void *res = NULL;
dom_node_type typ;
/* Only interested in element nodes */
exc = dom_node_get_node_type(node, &typ);
if (typ != DOM_ELEMENT_NODE) {
return NULL;
}
if (res = el_match_selector(selector, node)) {
/* There was an error; return */
return res;
}
/* Get the node's first child */
exc = dom_node_get_first_child(node, &child);
if (exc != DOM_NO_ERR) {
fprintf(stderr, "Exception raised for node_get_first_child\n");
return NULL;
} else if (child != NULL) {
/* node has children; decend to children's depth */
depth++;
/* Loop though all node's children */
do {
dom_node *next_child;
/* Visit node's descendents */
res = walk_tree_query(child, selector, depth);
/* There was an error; return */
if (res) {
dom_node_unref(child);
return res;
}
/* Go to next sibling */
exc = dom_node_get_next_sibling(child, &next_child);
if (exc != DOM_NO_ERR) {
fprintf(stderr, "Exception raised for "
"node_get_next_sibling\n");
dom_node_unref(child);
return NULL;
}
dom_node_unref(child);
child = next_child;
} while (child != NULL); /* No more children */
}
return NULL;
}
static bool
document_querySelector(JSContext *ctx, unsigned int argc, JS::Value *vp)
{
@ -1841,8 +1897,31 @@ document_querySelector(JSContext *ctx, unsigned int argc, JS::Value *vp)
args.rval().setNull();
return true;
}
// TODO
args.rval().setNull();
dom_node *root = NULL; /* root element of document */
/* Get root element */
dom_exception exc = dom_document_get_document_element(document->dom, &root);
if (exc != DOM_NO_ERR) {
args.rval().setNull();
return true;
}
char *selector = jsval_to_string(ctx, args[0]);
if (!selector) {
dom_node_unref(root);
args.rval().setNull();
return true;
}
void *ret = walk_tree_query(root, selector, 0);
mem_free(selector);
dom_node_unref(root);
if (!ret) {
args.rval().setNull();
} else {
JSObject *el = getElement(ctx, ret);
args.rval().setObject(*el);
}
return true;
}

View File

@ -11,6 +11,8 @@ function myFunction() {
var y = document.querySelector('.b');
console.assert(!(y === null), 'Class b');
var inp = y.innerHTML;
console.assert(inp === 'Class b.', 'Class b.');
}
console.error('document.querySelector.html');