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 <[email protected]>
Commit: Michael Drake <[email protected]>
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
[email protected]
http://listmaster.pepperfish.net/cgi-bin/mailman/listinfo/netsurf-commits-netsurf-browser.org