Gitweb links: ...log http://git.netsurf-browser.org/libcss.git/shortlog/f2edb01ba53ba2a0ee11a5cd5bbf5ec6bde3d46f ...commit http://git.netsurf-browser.org/libcss.git/commit/f2edb01ba53ba2a0ee11a5cd5bbf5ec6bde3d46f ...tree http://git.netsurf-browser.org/libcss.git/tree/f2edb01ba53ba2a0ee11a5cd5bbf5ec6bde3d46f
The branch, tlsa/shared-styles has been updated discards 6f69c83179bb5009584b9c642746ae966006f49d (commit) via f2edb01ba53ba2a0ee11a5cd5bbf5ec6bde3d46f (commit) This update added new revisions after undoing existing revisions. That is to say, the old revision is not a strict subset of the new revision. This situation occurs when you --force push a change and generate a repository containing something like this: * -- * -- B -- O -- O -- O (6f69c83179bb5009584b9c642746ae966006f49d) \ N -- N -- N (f2edb01ba53ba2a0ee11a5cd5bbf5ec6bde3d46f) When this happens we assume that you've already had alert emails for all of the O revisions, and so we here report only the revisions in the N branch from the common base, B. Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commitdiff http://git.netsurf-browser.org/libcss.git/commit/?id=f2edb01ba53ba2a0ee11a5cd5bbf5ec6bde3d46f commit f2edb01ba53ba2a0ee11a5cd5bbf5ec6bde3d46f Author: Michael Drake <t...@netsurf-browser.org> Commit: Michael Drake <t...@netsurf-browser.org> Work in Progress: Bypass selection by sharing previous sibling's style. diff --git a/src/select/select.c b/src/select/select.c index c1654bf..b122a98 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -713,6 +713,198 @@ static css_error css__set_node_data(void *node, css_select_state *state, } +enum share_candidate_type { + CANDIDATE_SIBLING, + CANDIDATE_COUSIN, +}; + +/** + * Check whether candidate node's ID or classes would prevent style sharing. + * + * \param[in] state The selection state for current node. + * \param[in] share_candidate_node The node to test id and classes of. + * \param[in] type The candidate's relation to selection node. + * \param[out] similar Returns true if id and classes don't + * prevent sharing. Returns false if + * they do. + * \return CSS_OK on success, appropriate error otherwise. + */ +static css_error css_select_style__get_sharable_node_data_for_candidate( + css_select_state *state, + void *share_candidate_node, + enum share_candidate_type type, + struct css_node_data **sharable_node_data) +{ + css_error error; + lwc_string *share_candidate_id; + uint32_t share_candidate_n_classes; + lwc_string **share_candidate_classes; + struct css_node_data *node_data; + + UNUSED(type); + + *sharable_node_data = NULL; + + /* We get the candidate node data first, as if it has none, we can't + * share its data anyway. + * Hideous casting to avoid warnings on all platforms we build for. */ + error = state->handler->get_libcss_node_data(state->pw, + share_candidate_node, (void **) (void *) &node_data); + if (error != CSS_OK || node_data == NULL) { + return error; + } + + /* If one node has hints and other doesn't then can't share */ + if ((node_data->flags & CSS_NODE_FLAGS_HAS_HINTS) != + (state->node_data->flags | CSS_NODE_FLAGS_HAS_HINTS)) { + return CSS_OK; + } + + /* If the node was affected by attribute or pseudo class rules, + * it's not a candidate for sharing */ + if (node_data->flags & ( + CSS_NODE_FLAGS_TAINT_PSEUDO_CLASS | + CSS_NODE_FLAGS_TAINT_ATTRIBUTE | + CSS_NODE_FLAGS_TAINT_SIBLING)) { + return CSS_OK; + } + + /* Check candidate ID doesn't prevent sharing */ + error = state->handler->node_id(state->pw, + share_candidate_node, + &share_candidate_id); + if (error != CSS_OK) { + return error; + + } else if (share_candidate_id != NULL) { + lwc_string_unref(share_candidate_id); + return CSS_OK; + } + + /* Check candidate classes don't prevent sharing */ + error = state->handler->node_classes(state->pw, + share_candidate_node, + &share_candidate_classes, + &share_candidate_n_classes); + if (error != CSS_OK) { + return error; + } + + if (state->n_classes != share_candidate_n_classes) { + return CSS_OK; + } + + /* TODO: no need to care about the order, but it's simpler to + * have an ordered match, and authors are more likely to be + * consistent than not. */ + for (uint32_t i = 0; i < share_candidate_n_classes; i++) { + bool match; + if (lwc_string_caseless_isequal( + state->classes[i], + share_candidate_classes[i], + &match) == lwc_error_ok && + match == false) { + return CSS_OK; + } + } + + if (node_data->flags & CSS_NODE_FLAGS_HAS_HINTS) { + /* TODO: check hints match. For now, just prevent sharing */ + return CSS_OK; + } + + *sharable_node_data = node_data; + + return CSS_OK; +} + + +static css_error css_select_style__get_named_cousin( + css_select_state *state, void *node, + void **share_candidate_node) +{ + /* TODO: + * + * Consider cousin nodes; Go to parent's previous sibling's last child. + */ + UNUSED(state); + UNUSED(node); + + *share_candidate_node = NULL; + + return CSS_OK; +} + + +static css_error css_select_style__get_sharable_node_data( + void *node, css_select_state *state, + struct css_node_data **sharable_node_data) +{ + css_error error; + enum share_candidate_type type = CANDIDATE_SIBLING; + + *sharable_node_data = NULL; + + /* TODO: move this test to caller? */ + if (state->id != NULL) { + /* If the node has an ID can't share another node's style. */ + /* TODO: Consider whether this ID exists in the ID hash tables. + * (If not, the ID cannot affect the node's style.) + * + * Call css__selector_hash_find_by_id, for each sheet, + * and if we get a non-NULL "matched" then return. + * + * Check overhead is worth cost. */ + return CSS_OK; + } + + while (true) { + void *share_candidate_node; + + /* Get previous sibling with same element name */ + error = state->handler->named_sibling_node(state->pw, + node, &state->element, &share_candidate_node); + if (error != CSS_OK) { + return error; + } else { + if (share_candidate_node == NULL) { + error = css_select_style__get_named_cousin( + state, node, + &share_candidate_node); + if (error != CSS_OK) { + return error; + } else { + if (share_candidate_node == NULL) { + break; + } + } + type = CANDIDATE_COUSIN; + } + } + + /* Check whether we can share the candidate node's + * style. We already know the element names match, + * check that candidate node's ID and class won't + * prevent sharing. */ + error = css_select_style__get_sharable_node_data_for_candidate( + state, share_candidate_node, + type, sharable_node_data); + if (error != CSS_OK) { + return error; + } else { + if (sharable_node_data == NULL) { + /* Can't share with this; look for another */ + continue; + } else { + break; + } + } + } + + return CSS_OK; +} + + /** * Finalise a selection state, releasing any resources it owns * @@ -862,6 +1054,7 @@ css_error css_select_style(css_select_ctx *ctx, void *node, css_select_state state; css_hint *hints = NULL; void *parent = NULL; + struct css_node_data *share; if (ctx == NULL || node == NULL || result == NULL || handler == NULL || handler->handler_version != CSS_SELECT_HANDLER_VERSION_1) @@ -876,11 +1069,29 @@ css_error css_select_style(css_select_ctx *ctx, void *node, if (error != CSS_OK) return error; - /* Apply presentational hints */ + /* Fetch presentational hints */ error = handler->node_presentational_hint(pw, node, &nhints, &hints); if (error != CSS_OK) goto cleanup; if (nhints > 0) { + state.node_data->flags |= CSS_NODE_FLAGS_HAS_HINTS; + } + + /* Check if we can share another node's style */ + error = css_select_style__get_sharable_node_data(node, &state, &share); + if (error != CSS_OK) { + goto cleanup; + } else if (share != NULL) { + css_computed_style **styles = share->partial.styles; + for (i = 0; i < CSS_PSEUDO_ELEMENT_COUNT; i++) { + state.results->styles[i] = + css__computed_style_ref(styles[i]); + } + goto complete; + } + + /* Apply any hints */ + if (nhints > 0) { /* Ensure that the appropriate computed style exists */ struct css_computed_style *computed_style = state.results->styles[CSS_PSEUDO_ELEMENT_NONE]; @@ -1009,6 +1220,7 @@ css_error css_select_style(css_select_ctx *ctx, void *node, } } +complete: error = css__set_node_data(node, &state, handler, pw); if (error != CSS_OK) { goto cleanup; @@ -2043,6 +2255,10 @@ css_error match_named_combinator(css_select_ctx *ctx, css_combinator type, n, &selector->data.qname, &n); if (error != CSS_OK) return error; + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_SIBLING; + } break; case CSS_COMBINATOR_GENERIC_SIBLING: error = state->handler->named_generic_sibling_node( @@ -2050,6 +2266,10 @@ css_error match_named_combinator(css_select_ctx *ctx, css_combinator type, &n); if (error != CSS_OK) return error; + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_SIBLING; + } case CSS_COMBINATOR_NONE: break; } @@ -2138,6 +2358,10 @@ css_error match_universal_combinator(css_select_ctx *ctx, css_combinator type, error = state->handler->sibling_node(state->pw, n, &n); if (error != CSS_OK) return error; + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_SIBLING; + } break; case CSS_COMBINATOR_NONE: break; @@ -2405,8 +2629,17 @@ css_error match_detail(css_select_ctx *ctx, void *node, } else if (detail->qname.name == ctx->checked) { error = state->handler->node_is_checked(state->pw, node, match); - } else + } else { *match = false; + } + /* If the node in question is the node we're selecting for + * then its style has been tainted by pseudo class specific + * rules. We don't care whether the rule matched or not, + * just that such rule has been considered. */ + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_PSEUDO_CLASS; + } break; case CSS_SELECTOR_PSEUDO_ELEMENT: *match = true; @@ -2425,36 +2658,68 @@ css_error match_detail(css_select_ctx *ctx, void *node, case CSS_SELECTOR_ATTRIBUTE: error = state->handler->node_has_attribute(state->pw, node, &detail->qname, match); + /* If the node in question is the node we're selecting for + * then its style has been tainted by attribute specific + * rules. We don't care whether the rule matched or not, + * just that such rule has been considered. */ + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_ATTRIBUTE; + } break; case CSS_SELECTOR_ATTRIBUTE_EQUAL: error = state->handler->node_has_attribute_equal(state->pw, node, &detail->qname, detail->value.string, match); + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_ATTRIBUTE; + } break; case CSS_SELECTOR_ATTRIBUTE_DASHMATCH: error = state->handler->node_has_attribute_dashmatch(state->pw, node, &detail->qname, detail->value.string, match); + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_ATTRIBUTE; + } break; case CSS_SELECTOR_ATTRIBUTE_INCLUDES: error = state->handler->node_has_attribute_includes(state->pw, node, &detail->qname, detail->value.string, match); + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_ATTRIBUTE; + } break; case CSS_SELECTOR_ATTRIBUTE_PREFIX: error = state->handler->node_has_attribute_prefix(state->pw, node, &detail->qname, detail->value.string, match); + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_ATTRIBUTE; + } break; case CSS_SELECTOR_ATTRIBUTE_SUFFIX: error = state->handler->node_has_attribute_suffix(state->pw, node, &detail->qname, detail->value.string, match); + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_ATTRIBUTE; + } break; case CSS_SELECTOR_ATTRIBUTE_SUBSTRING: error = state->handler->node_has_attribute_substring(state->pw, node, &detail->qname, detail->value.string, match); + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_ATTRIBUTE; + } break; } diff --git a/src/select/select.h b/src/select/select.h index 254b095..96f4546 100644 --- a/src/select/select.h +++ b/src/select/select.h @@ -34,6 +34,13 @@ typedef struct prop_state { struct css_node_data { css_select_results partial; css_bloom *bloom; + enum { + CSS_NODE_FLAGS_NONE = 0, + CSS_NODE_FLAGS_HAS_HINTS = (1 << 0), + CSS_NODE_FLAGS_TAINT_PSEUDO_CLASS = (1 << 1), + CSS_NODE_FLAGS_TAINT_ATTRIBUTE = (1 << 2), + CSS_NODE_FLAGS_TAINT_SIBLING = (1 << 3), + } flags; }; /** ----------------------------------------------------------------------- Summary of changes: src/select/select.c | 169 +++++++++++++++++++++++++++++++++++++-------------- src/select/select.h | 7 ++- 2 files changed, 130 insertions(+), 46 deletions(-) diff --git a/src/select/select.c b/src/select/select.c index e63db50..b122a98 100644 --- a/src/select/select.c +++ b/src/select/select.c @@ -712,21 +712,27 @@ static css_error css__set_node_data(void *node, css_select_state *state, return CSS_OK; } -#if 0 + +enum share_candidate_type { + CANDIDATE_SIBLING, + CANDIDATE_COUSIN, +}; /** * Check whether candidate node's ID or classes would prevent style sharing. * - * \param[in] share_candidate_node The node to test id and classes of. * \param[in] state The selection state for current node. + * \param[in] share_candidate_node The node to test id and classes of. + * \param[in] type The candidate's relation to selection node. * \param[out] similar Returns true if id and classes don't * prevent sharing. Returns false if * they do. * \return CSS_OK on success, appropriate error otherwise. */ static css_error css_select_style__get_sharable_node_data_for_candidate( - void *share_candidate_node, css_select_state *state, + void *share_candidate_node, + enum share_candidate_type type, struct css_node_data **sharable_node_data) { css_error error; @@ -735,8 +741,35 @@ static css_error css_select_style__get_sharable_node_data_for_candidate( lwc_string **share_candidate_classes; struct css_node_data *node_data; + UNUSED(type); + *sharable_node_data = NULL; + /* We get the candidate node data first, as if it has none, we can't + * share its data anyway. + * Hideous casting to avoid warnings on all platforms we build for. */ + error = state->handler->get_libcss_node_data(state->pw, + share_candidate_node, (void **) (void *) &node_data); + if (error != CSS_OK || node_data == NULL) { + return error; + } + + /* If one node has hints and other doesn't then can't share */ + if ((node_data->flags & CSS_NODE_FLAGS_HAS_HINTS) != + (state->node_data->flags | CSS_NODE_FLAGS_HAS_HINTS)) { + return CSS_OK; + } + + /* If the node was affected by attribute or pseudo class rules, + * it's not a candidate for sharing */ + if (node_data->flags & ( + CSS_NODE_FLAGS_TAINT_PSEUDO_CLASS | + CSS_NODE_FLAGS_TAINT_ATTRIBUTE | + CSS_NODE_FLAGS_TAINT_SIBLING)) { + return CSS_OK; + } + + /* Check candidate ID doesn't prevent sharing */ error = state->handler->node_id(state->pw, share_candidate_node, &share_candidate_id); @@ -748,6 +781,7 @@ static css_error css_select_style__get_sharable_node_data_for_candidate( return CSS_OK; } + /* Check candidate classes don't prevent sharing */ error = state->handler->node_classes(state->pw, share_candidate_node, &share_candidate_classes, @@ -761,7 +795,8 @@ static css_error css_select_style__get_sharable_node_data_for_candidate( } /* TODO: no need to care about the order, but it's simpler to - * have an ordered match */ + * have an ordered match, and authors are more likely to be + * consistent than not. */ for (uint32_t i = 0; i < share_candidate_n_classes; i++) { bool match; if (lwc_string_caseless_isequal( @@ -773,29 +808,12 @@ static css_error css_select_style__get_sharable_node_data_for_candidate( } } - /* Hideous casting to avoid warnings on all platforms - * we build for. */ - error = state->handler->get_libcss_node_data(state->pw, - share_candidate_node, (void **) (void *) &node_data); - if (error != CSS_OK || node_data == NULL) { - return error; - } - - /* If one one node has hints and other doesn't then can't share */ - if ((node_data->flags & CSS_NODE_FLAGS_HAS_HINTS) != - (state->node_data->flags & CSS_NODE_FLAGS_HAS_HINTS)) { - return CSS_OK; - } - if (node_data->flags & CSS_NODE_FLAGS_HAS_HINTS) { /* TODO: check hints match. For now, just prevent sharing */ return CSS_OK; } - /* TDOD: check candidate wasn't affected by pseudo-class, attribute - * or sibling selectores */ - - sharable_node_data = node_data; + *sharable_node_data = node_data; return CSS_OK; } @@ -807,7 +825,7 @@ static css_error css_select_style__get_named_cousin( { /* TODO: * - * Consider cousin nodes; Go to parent's prev sibling's last child. + * Consider cousin nodes; Go to parent's previous sibling's last child. */ UNUSED(state); UNUSED(node); @@ -818,14 +836,14 @@ static css_error css_select_style__get_named_cousin( } -static css_error css_select_style__get_sharable_node_data(css_select_ctx *ctx, - void *node, uint64_t media, css_select_state *state, +static css_error css_select_style__get_sharable_node_data( + void *node, css_select_state *state, struct css_node_data **sharable_node_data) { css_error error; + enum share_candidate_type type = CANDIDATE_SIBLING; - UNUSED(ctx); - UNUSED(media); + *sharable_node_data = NULL; /* TODO: move this test to caller? */ if (state->id != NULL) { @@ -837,13 +855,11 @@ static css_error css_select_style__get_sharable_node_data(css_select_ctx *ctx, * and if we get a non-NULL "matched" then return. * * Check overhead is worth cost. */ - *sharable_node_data = NULL; return CSS_OK; } while (true) { void *share_candidate_node; - struct css_node_data *share_node_data; /* Get previous sibling with same element name */ error = state->handler->named_sibling_node(state->pw, @@ -862,6 +878,7 @@ static css_error css_select_style__get_sharable_node_data(css_select_ctx *ctx, break; } } + type = CANDIDATE_COUSIN; } } @@ -870,20 +887,22 @@ static css_error css_select_style__get_sharable_node_data(css_select_ctx *ctx, * check that candidate node's ID and class won't * prevent sharing. */ error = css_select_style__get_sharable_node_data_for_candidate( - share_candidate_node, state, &share_node_data); + state, share_candidate_node, + type, sharable_node_data); if (error != CSS_OK) { return error; } else { - if (share_node_data == NULL) { + if (sharable_node_data == NULL) { /* Can't share with this; look for another */ continue; + } else { + break; } } } return CSS_OK; } -#endif /** @@ -1035,6 +1054,7 @@ css_error css_select_style(css_select_ctx *ctx, void *node, css_select_state state; css_hint *hints = NULL; void *parent = NULL; + struct css_node_data *share; if (ctx == NULL || node == NULL || result == NULL || handler == NULL || handler->handler_version != CSS_SELECT_HANDLER_VERSION_1) @@ -1049,11 +1069,29 @@ css_error css_select_style(css_select_ctx *ctx, void *node, if (error != CSS_OK) return error; - /* Apply presentational hints */ + /* Fetch presentational hints */ error = handler->node_presentational_hint(pw, node, &nhints, &hints); if (error != CSS_OK) goto cleanup; if (nhints > 0) { + state.node_data->flags |= CSS_NODE_FLAGS_HAS_HINTS; + } + + /* Check if we can share another node's style */ + error = css_select_style__get_sharable_node_data(node, &state, &share); + if (error != CSS_OK) { + goto cleanup; + } else if (share != NULL) { + css_computed_style **styles = share->partial.styles; + for (i = 0; i < CSS_PSEUDO_ELEMENT_COUNT; i++) { + state.results->styles[i] = + css__computed_style_ref(styles[i]); + } + goto complete; + } + + /* Apply any hints */ + if (nhints > 0) { /* Ensure that the appropriate computed style exists */ struct css_computed_style *computed_style = state.results->styles[CSS_PSEUDO_ELEMENT_NONE]; @@ -1070,16 +1108,8 @@ css_error css_select_style(css_select_ctx *ctx, void *node, if (error != CSS_OK) goto cleanup; } - - state.node_data->flags |= CSS_NODE_FLAGS_HAS_HINTS; } -/* - if (we_found_a_style_to_share) { - goto complete; - } -*/ - /* Iterate through the top-level stylesheets, selecting styles * from those which apply to our current media requirements and * are not disabled */ @@ -1190,9 +1220,7 @@ css_error css_select_style(css_select_ctx *ctx, void *node, } } -/* complete: -*/ error = css__set_node_data(node, &state, handler, pw); if (error != CSS_OK) { goto cleanup; @@ -2227,6 +2255,10 @@ css_error match_named_combinator(css_select_ctx *ctx, css_combinator type, n, &selector->data.qname, &n); if (error != CSS_OK) return error; + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_SIBLING; + } break; case CSS_COMBINATOR_GENERIC_SIBLING: error = state->handler->named_generic_sibling_node( @@ -2234,6 +2266,10 @@ css_error match_named_combinator(css_select_ctx *ctx, css_combinator type, &n); if (error != CSS_OK) return error; + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_SIBLING; + } case CSS_COMBINATOR_NONE: break; } @@ -2322,6 +2358,10 @@ css_error match_universal_combinator(css_select_ctx *ctx, css_combinator type, error = state->handler->sibling_node(state->pw, n, &n); if (error != CSS_OK) return error; + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_SIBLING; + } break; case CSS_COMBINATOR_NONE: break; @@ -2589,8 +2629,17 @@ css_error match_detail(css_select_ctx *ctx, void *node, } else if (detail->qname.name == ctx->checked) { error = state->handler->node_is_checked(state->pw, node, match); - } else + } else { *match = false; + } + /* If the node in question is the node we're selecting for + * then its style has been tainted by pseudo class specific + * rules. We don't care whether the rule matched or not, + * just that such rule has been considered. */ + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_PSEUDO_CLASS; + } break; case CSS_SELECTOR_PSEUDO_ELEMENT: *match = true; @@ -2609,36 +2658,68 @@ css_error match_detail(css_select_ctx *ctx, void *node, case CSS_SELECTOR_ATTRIBUTE: error = state->handler->node_has_attribute(state->pw, node, &detail->qname, match); + /* If the node in question is the node we're selecting for + * then its style has been tainted by attribute specific + * rules. We don't care whether the rule matched or not, + * just that such rule has been considered. */ + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_ATTRIBUTE; + } break; case CSS_SELECTOR_ATTRIBUTE_EQUAL: error = state->handler->node_has_attribute_equal(state->pw, node, &detail->qname, detail->value.string, match); + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_ATTRIBUTE; + } break; case CSS_SELECTOR_ATTRIBUTE_DASHMATCH: error = state->handler->node_has_attribute_dashmatch(state->pw, node, &detail->qname, detail->value.string, match); + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_ATTRIBUTE; + } break; case CSS_SELECTOR_ATTRIBUTE_INCLUDES: error = state->handler->node_has_attribute_includes(state->pw, node, &detail->qname, detail->value.string, match); + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_ATTRIBUTE; + } break; case CSS_SELECTOR_ATTRIBUTE_PREFIX: error = state->handler->node_has_attribute_prefix(state->pw, node, &detail->qname, detail->value.string, match); + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_ATTRIBUTE; + } break; case CSS_SELECTOR_ATTRIBUTE_SUFFIX: error = state->handler->node_has_attribute_suffix(state->pw, node, &detail->qname, detail->value.string, match); + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_ATTRIBUTE; + } break; case CSS_SELECTOR_ATTRIBUTE_SUBSTRING: error = state->handler->node_has_attribute_substring(state->pw, node, &detail->qname, detail->value.string, match); + if (node == state->node) { + state->node_data->flags |= + CSS_NODE_FLAGS_TAINT_ATTRIBUTE; + } break; } diff --git a/src/select/select.h b/src/select/select.h index d4d5dbb..96f4546 100644 --- a/src/select/select.h +++ b/src/select/select.h @@ -35,8 +35,11 @@ struct css_node_data { css_select_results partial; css_bloom *bloom; enum { - CSS_NODE_FLAGS_NONE = 0, - CSS_NODE_FLAGS_HAS_HINTS = (1 << 0), + CSS_NODE_FLAGS_NONE = 0, + CSS_NODE_FLAGS_HAS_HINTS = (1 << 0), + CSS_NODE_FLAGS_TAINT_PSEUDO_CLASS = (1 << 1), + CSS_NODE_FLAGS_TAINT_ATTRIBUTE = (1 << 2), + CSS_NODE_FLAGS_TAINT_SIBLING = (1 << 3), } flags; }; -- Cascading Style Sheets library _______________________________________________ netsurf-commits mailing list netsurf-commits@netsurf-browser.org http://listmaster.pepperfish.net/cgi-bin/mailman/listinfo/netsurf-commits-netsurf-browser.org