mirror of
https://github.com/rkd77/elinks.git
synced 2025-06-30 22:19:29 -04:00
CSS bug 766: Scan ancestor elements only if needed.
time elinks -no-connect -no-home 'http://rss.slashdot.org/Slashdot/slashdot/to?m=5878' Wait until finished loading, then press q and Enter. before 6.45user 0.17system 0:11.34elapsed 58%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+3387minor)pagefaults 0swaps after 5.51user 0.14system 0:09.85elapsed 57%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+3469minor)pagefaults 0swaps before 5.86user 0.17system 0:10.58elapsed 57%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+3504minor)pagefaults 0swaps after 5.50user 0.15system 0:10.96elapsed 51%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+3645minor)pagefaults 0swaps before 6.40user 0.14system 0:11.85elapsed 55%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+3640minor)pagefaults 0swaps after 6.17user 0.12system 0:10.80elapsed 58%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+3378minor)pagefaults 0swaps before 5.80user 0.14system 0:10.29elapsed 57%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+3632minor)pagefaults 0swaps after 5.56user 0.16system 0:10.08elapsed 56%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+3569minor)pagefaults 0swaps before 5.92user 0.14system 0:10.54elapsed 57%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+3570minor)pagefaults 0swaps after 5.52user 0.13system 0:10.10elapsed 55%CPU (0avgtext+0avgdata 0maxresident)k 0inputs+0outputs (0major+3515minor)pagefaults 0swaps All in all, it is doubtful whether this change is worth the complexity. Please go ahead and revert if you think it isn't.
This commit is contained in:
parent
ace03d5093
commit
591ff81890
@ -141,7 +141,8 @@ examine_element(struct html_context *html_context, struct css_selector *base,
|
|||||||
dbginfo(sel, type, base); \
|
dbginfo(sel, type, base); \
|
||||||
merge_css_selectors(base, sel); \
|
merge_css_selectors(base, sel); \
|
||||||
/* Ancestor matches? */ \
|
/* Ancestor matches? */ \
|
||||||
if ((struct list_head *) element->next \
|
if (sel->leaves.may_contain_rel_ancestor \
|
||||||
|
&& (struct list_head *) element->next \
|
||||||
!= &html_context->stack) { \
|
!= &html_context->stack) { \
|
||||||
struct html_element *ancestor; \
|
struct html_element *ancestor; \
|
||||||
/* This is less effective than doing reverse iterations,
|
/* This is less effective than doing reverse iterations,
|
||||||
@ -227,7 +228,7 @@ get_css_selector_for_element(struct html_context *html_context,
|
|||||||
|
|
||||||
assert(element && element->options && css);
|
assert(element && element->options && css);
|
||||||
|
|
||||||
selector = init_css_selector(NULL, CST_ELEMENT, NULL, 0);
|
selector = init_css_selector(NULL, CST_ELEMENT, CSR_ROOT, NULL, 0);
|
||||||
if (!selector)
|
if (!selector)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -247,7 +248,7 @@ get_css_selector_for_element(struct html_context *html_context,
|
|||||||
struct css_selector *stylesel;
|
struct css_selector *stylesel;
|
||||||
struct scanner scanner;
|
struct scanner scanner;
|
||||||
|
|
||||||
stylesel = init_css_selector(NULL, CST_ELEMENT, NULL, 0);
|
stylesel = init_css_selector(NULL, CST_ELEMENT, CSR_ROOT, NULL, 0);
|
||||||
|
|
||||||
if (stylesel) {
|
if (stylesel) {
|
||||||
init_scanner(&scanner, &css_scanner_info, code, NULL);
|
init_scanner(&scanner, &css_scanner_info, code, NULL);
|
||||||
|
@ -386,7 +386,7 @@ css_parse_selector(struct css_stylesheet *css, struct scanner *scanner,
|
|||||||
* wasn't marked so and thus wasn't bound to
|
* wasn't marked so and thus wasn't bound to
|
||||||
* the stylesheet. Let's do that now. */
|
* the stylesheet. Let's do that now. */
|
||||||
assert(prev_element_selector);
|
assert(prev_element_selector);
|
||||||
prev_element_selector->relation = CSR_ROOT;
|
set_css_selector_relation(prev_element_selector, CSR_ROOT);
|
||||||
prev_element_selector =
|
prev_element_selector =
|
||||||
reparent_selector(&css->selectors,
|
reparent_selector(&css->selectors,
|
||||||
prev_element_selector,
|
prev_element_selector,
|
||||||
@ -404,11 +404,11 @@ css_parse_selector(struct css_stylesheet *css, struct scanner *scanner,
|
|||||||
if (!selector) continue;
|
if (!selector) continue;
|
||||||
|
|
||||||
assert(prev_element_selector);
|
assert(prev_element_selector);
|
||||||
|
set_css_selector_relation(prev_element_selector, reltype);
|
||||||
add_css_selector_to_set(prev_element_selector,
|
add_css_selector_to_set(prev_element_selector,
|
||||||
&selector->leaves);
|
&selector->leaves);
|
||||||
last_chained_selector = prev_element_selector;
|
last_chained_selector = prev_element_selector;
|
||||||
|
|
||||||
prev_element_selector->relation = reltype;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,7 +45,9 @@ find_css_selector(struct css_selector_set *sels, enum css_selector_type type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct css_selector *
|
struct css_selector *
|
||||||
init_css_selector(struct css_selector_set *sels, enum css_selector_type type,
|
init_css_selector(struct css_selector_set *sels,
|
||||||
|
enum css_selector_type type,
|
||||||
|
enum css_selector_relation relation,
|
||||||
unsigned char *name, int namelen)
|
unsigned char *name, int namelen)
|
||||||
{
|
{
|
||||||
struct css_selector *selector;
|
struct css_selector *selector;
|
||||||
@ -53,7 +55,7 @@ init_css_selector(struct css_selector_set *sels, enum css_selector_type type,
|
|||||||
selector = mem_calloc(1, sizeof(*selector));
|
selector = mem_calloc(1, sizeof(*selector));
|
||||||
if (!selector) return NULL;
|
if (!selector) return NULL;
|
||||||
|
|
||||||
selector->relation = CSR_ROOT; /* Default */
|
selector->relation = relation;
|
||||||
init_css_selector_set(&selector->leaves);
|
init_css_selector_set(&selector->leaves);
|
||||||
|
|
||||||
selector->type = type;
|
selector->type = type;
|
||||||
@ -78,6 +80,17 @@ init_css_selector(struct css_selector_set *sels, enum css_selector_type type,
|
|||||||
return selector;
|
return selector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
set_css_selector_relation(struct css_selector *selector,
|
||||||
|
enum css_selector_relation relation)
|
||||||
|
{
|
||||||
|
/* Changing the relation after the selector is in a set might
|
||||||
|
* require setting css_relation_set.may_contain_rel_ancestor,
|
||||||
|
* but we don't have a pointer to the set here. */
|
||||||
|
assert(!css_selector_is_in_set(selector));
|
||||||
|
selector->relation = relation;
|
||||||
|
}
|
||||||
|
|
||||||
struct css_selector *
|
struct css_selector *
|
||||||
get_css_selector(struct css_selector_set *sels, enum css_selector_type type,
|
get_css_selector(struct css_selector_set *sels, enum css_selector_type type,
|
||||||
enum css_selector_relation rel,
|
enum css_selector_relation rel,
|
||||||
@ -91,13 +104,7 @@ get_css_selector(struct css_selector_set *sels, enum css_selector_type type,
|
|||||||
return selector;
|
return selector;
|
||||||
}
|
}
|
||||||
|
|
||||||
selector = init_css_selector(sels, type, name, namelen);
|
return init_css_selector(sels, type, rel, name, namelen);
|
||||||
if (selector) {
|
|
||||||
selector->relation = rel;
|
|
||||||
return selector;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct css_selector *
|
static struct css_selector *
|
||||||
@ -106,8 +113,9 @@ copy_css_selector(struct css_stylesheet *css, struct css_selector *orig)
|
|||||||
struct css_selector *copy;
|
struct css_selector *copy;
|
||||||
|
|
||||||
assert(css && orig);
|
assert(css && orig);
|
||||||
|
assert(orig->relation == CSR_ROOT);
|
||||||
|
|
||||||
copy = init_css_selector(&css->selectors, orig->type,
|
copy = init_css_selector(&css->selectors, orig->type, CSR_ROOT,
|
||||||
orig->name, strlen(orig->name));
|
orig->name, strlen(orig->name));
|
||||||
if (!copy)
|
if (!copy)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -183,6 +191,13 @@ done_css_selector(struct css_selector *selector)
|
|||||||
mem_free(selector);
|
mem_free(selector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
init_css_selector_set(struct css_selector_set *set)
|
||||||
|
{
|
||||||
|
set->may_contain_rel_ancestor = 0;
|
||||||
|
init_list(set->list);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
done_css_selector_set(struct css_selector_set *set)
|
done_css_selector_set(struct css_selector_set *set)
|
||||||
{
|
{
|
||||||
@ -191,6 +206,25 @@ done_css_selector_set(struct css_selector_set *set)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
add_css_selector_to_set(struct css_selector *selector,
|
||||||
|
struct css_selector_set *set)
|
||||||
|
{
|
||||||
|
assert(!css_selector_is_in_set(selector));
|
||||||
|
|
||||||
|
add_to_list(set->list, selector);
|
||||||
|
if (selector->relation == CSR_ANCESTOR)
|
||||||
|
set->may_contain_rel_ancestor = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
del_css_selector_from_set(struct css_selector *selector)
|
||||||
|
{
|
||||||
|
del_from_list(selector);
|
||||||
|
selector->next = NULL;
|
||||||
|
selector->prev = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_CSS
|
#ifdef DEBUG_CSS
|
||||||
void
|
void
|
||||||
dump_css_selector_tree_iter(struct css_selector_set *sels, int level)
|
dump_css_selector_tree_iter(struct css_selector_set *sels, int level)
|
||||||
|
@ -41,19 +41,14 @@
|
|||||||
* because all rules for the same selector have already been merged
|
* because all rules for the same selector have already been merged
|
||||||
* into one struct css_selector. */
|
* into one struct css_selector. */
|
||||||
struct css_selector_set {
|
struct css_selector_set {
|
||||||
#ifdef CONFIG_DEBUG
|
unsigned char may_contain_rel_ancestor;
|
||||||
/* Cause a crash if struct css_selector_set * is cast to
|
|
||||||
* struct list_head *. */
|
|
||||||
char dummy;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
/* Keep this away from the beginning of the structure,
|
||||||
|
* so that nobody can cast the struct css_selector_set *
|
||||||
|
* to struct list_head * and get away with it. */
|
||||||
struct list_head list; /* -> struct css_selector */
|
struct list_head list; /* -> struct css_selector */
|
||||||
};
|
};
|
||||||
#ifdef CONFIG_DEBUG
|
|
||||||
#define INIT_CSS_SELECTOR_SET(set) { 0, { D_LIST_HEAD(set.list) } }
|
#define INIT_CSS_SELECTOR_SET(set) { 0, { D_LIST_HEAD(set.list) } }
|
||||||
#else
|
|
||||||
# define INIT_CSS_SELECTOR_SET(set) { { D_LIST_HEAD(set.list) } }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* The {struct css_selector} is used for mapping elements (or nodes) in the
|
/* The {struct css_selector} is used for mapping elements (or nodes) in the
|
||||||
* document structure to properties. See README for some hints about how the
|
* document structure to properties. See README for some hints about how the
|
||||||
@ -65,7 +60,8 @@ struct css_selector {
|
|||||||
LIST_HEAD(struct css_selector);
|
LIST_HEAD(struct css_selector);
|
||||||
|
|
||||||
/* This defines relation between this selector fragment and its
|
/* This defines relation between this selector fragment and its
|
||||||
* parent in the selector tree. */
|
* parent in the selector tree.
|
||||||
|
* Update with set_css_selector_relation(). */
|
||||||
enum css_selector_relation {
|
enum css_selector_relation {
|
||||||
CSR_ROOT, /* First class stylesheet member. */
|
CSR_ROOT, /* First class stylesheet member. */
|
||||||
CSR_SPECIFITY, /* Narrowing-down, i.e. the "x" in "foo#x". */
|
CSR_SPECIFITY, /* Narrowing-down, i.e. the "x" in "foo#x". */
|
||||||
@ -152,6 +148,7 @@ struct css_selector *find_css_selector(struct css_selector_set *set,
|
|||||||
* your POV. */
|
* your POV. */
|
||||||
struct css_selector *init_css_selector(struct css_selector_set *set,
|
struct css_selector *init_css_selector(struct css_selector_set *set,
|
||||||
enum css_selector_type type,
|
enum css_selector_type type,
|
||||||
|
enum css_selector_relation relation,
|
||||||
unsigned char *name, int namelen);
|
unsigned char *name, int namelen);
|
||||||
|
|
||||||
/* Add all properties from the list to the given @selector. */
|
/* Add all properties from the list to the given @selector. */
|
||||||
@ -161,15 +158,19 @@ void add_selector_properties(struct css_selector *selector,
|
|||||||
/* Join @sel2 to @sel1, @sel1 taking precedence in all conflicts. */
|
/* Join @sel2 to @sel1, @sel1 taking precedence in all conflicts. */
|
||||||
void merge_css_selectors(struct css_selector *sel1, struct css_selector *sel2);
|
void merge_css_selectors(struct css_selector *sel1, struct css_selector *sel2);
|
||||||
|
|
||||||
|
/* Use this function instead of modifying css_selector.relation directly. */
|
||||||
|
void set_css_selector_relation(struct css_selector *,
|
||||||
|
enum css_selector_relation);
|
||||||
|
|
||||||
/* Destroy a selector. done_css_stylesheet() normally does that for you. */
|
/* Destroy a selector. done_css_stylesheet() normally does that for you. */
|
||||||
void done_css_selector(struct css_selector *selector);
|
void done_css_selector(struct css_selector *selector);
|
||||||
|
|
||||||
#define init_css_selector_set(set) init_list((set)->list)
|
void init_css_selector_set(struct css_selector_set *set);
|
||||||
void done_css_selector_set(struct css_selector_set *set);
|
void done_css_selector_set(struct css_selector_set *set);
|
||||||
#define css_selector_set_empty(set) list_empty((set)->list)
|
#define css_selector_set_empty(set) list_empty((set)->list)
|
||||||
#define css_selector_set_front(set) ((struct css_selector *) ((set)->list.next))
|
#define css_selector_set_front(set) ((struct css_selector *) ((set)->list.next))
|
||||||
#define del_css_selector_from_set(selector) del_from_list(selector)
|
void add_css_selector_to_set(struct css_selector *, struct css_selector_set *);
|
||||||
#define add_css_selector_to_set(selector, set) add_to_list((set)->list, (selector))
|
void del_css_selector_from_set(struct css_selector *);
|
||||||
#define css_selector_is_in_set(selector) ((selector)->next != NULL)
|
#define css_selector_is_in_set(selector) ((selector)->next != NULL)
|
||||||
#define foreach_css_selector(selector, set) foreach (selector, (set)->list)
|
#define foreach_css_selector(selector, set) foreach (selector, (set)->list)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user