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

Reply via email to