mirror of
https://github.com/rkd77/elinks.git
synced 2024-11-04 08:17:17 -05: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); \
|
||||
merge_css_selectors(base, sel); \
|
||||
/* Ancestor matches? */ \
|
||||
if ((struct list_head *) element->next \
|
||||
if (sel->leaves.may_contain_rel_ancestor \
|
||||
&& (struct list_head *) element->next \
|
||||
!= &html_context->stack) { \
|
||||
struct html_element *ancestor; \
|
||||
/* 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);
|
||||
|
||||
selector = init_css_selector(NULL, CST_ELEMENT, NULL, 0);
|
||||
selector = init_css_selector(NULL, CST_ELEMENT, CSR_ROOT, NULL, 0);
|
||||
if (!selector)
|
||||
return NULL;
|
||||
|
||||
@ -247,7 +248,7 @@ get_css_selector_for_element(struct html_context *html_context,
|
||||
struct css_selector *stylesel;
|
||||
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) {
|
||||
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
|
||||
* the stylesheet. Let's do that now. */
|
||||
assert(prev_element_selector);
|
||||
prev_element_selector->relation = CSR_ROOT;
|
||||
set_css_selector_relation(prev_element_selector, CSR_ROOT);
|
||||
prev_element_selector =
|
||||
reparent_selector(&css->selectors,
|
||||
prev_element_selector,
|
||||
@ -404,11 +404,11 @@ css_parse_selector(struct css_stylesheet *css, struct scanner *scanner,
|
||||
if (!selector) continue;
|
||||
|
||||
assert(prev_element_selector);
|
||||
set_css_selector_relation(prev_element_selector, reltype);
|
||||
add_css_selector_to_set(prev_element_selector,
|
||||
&selector->leaves);
|
||||
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 *
|
||||
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)
|
||||
{
|
||||
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));
|
||||
if (!selector) return NULL;
|
||||
|
||||
selector->relation = CSR_ROOT; /* Default */
|
||||
selector->relation = relation;
|
||||
init_css_selector_set(&selector->leaves);
|
||||
|
||||
selector->type = type;
|
||||
@ -78,6 +80,17 @@ init_css_selector(struct css_selector_set *sels, enum css_selector_type type,
|
||||
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 *
|
||||
get_css_selector(struct css_selector_set *sels, enum css_selector_type type,
|
||||
enum css_selector_relation rel,
|
||||
@ -91,13 +104,7 @@ get_css_selector(struct css_selector_set *sels, enum css_selector_type type,
|
||||
return selector;
|
||||
}
|
||||
|
||||
selector = init_css_selector(sels, type, name, namelen);
|
||||
if (selector) {
|
||||
selector->relation = rel;
|
||||
return selector;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return init_css_selector(sels, type, rel, name, namelen);
|
||||
}
|
||||
|
||||
static struct css_selector *
|
||||
@ -106,8 +113,9 @@ copy_css_selector(struct css_stylesheet *css, struct css_selector *orig)
|
||||
struct css_selector *copy;
|
||||
|
||||
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));
|
||||
if (!copy)
|
||||
return NULL;
|
||||
@ -183,6 +191,13 @@ done_css_selector(struct css_selector *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
|
||||
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
|
||||
void
|
||||
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
|
||||
* into one struct css_selector. */
|
||||
struct css_selector_set {
|
||||
#ifdef CONFIG_DEBUG
|
||||
/* Cause a crash if struct css_selector_set * is cast to
|
||||
* struct list_head *. */
|
||||
char dummy;
|
||||
#endif
|
||||
|
||||
unsigned char may_contain_rel_ancestor;
|
||||
|
||||
/* 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 */
|
||||
};
|
||||
#ifdef CONFIG_DEBUG
|
||||
# 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
|
||||
#define INIT_CSS_SELECTOR_SET(set) { 0, { D_LIST_HEAD(set.list) } }
|
||||
|
||||
/* 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
|
||||
@ -65,7 +60,8 @@ struct css_selector {
|
||||
LIST_HEAD(struct css_selector);
|
||||
|
||||
/* 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 {
|
||||
CSR_ROOT, /* First class stylesheet member. */
|
||||
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. */
|
||||
struct css_selector *init_css_selector(struct css_selector_set *set,
|
||||
enum css_selector_type type,
|
||||
enum css_selector_relation relation,
|
||||
unsigned char *name, int namelen);
|
||||
|
||||
/* 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. */
|
||||
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. */
|
||||
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);
|
||||
#define css_selector_set_empty(set) list_empty((set)->list)
|
||||
#define css_selector_set_front(set) ((struct css_selector *) ((set)->list.next))
|
||||
#define del_css_selector_from_set(selector) del_from_list(selector)
|
||||
#define add_css_selector_to_set(selector, set) add_to_list((set)->list, (selector))
|
||||
void add_css_selector_to_set(struct css_selector *, struct css_selector_set *);
|
||||
void del_css_selector_from_set(struct css_selector *);
|
||||
#define css_selector_is_in_set(selector) ((selector)->next != NULL)
|
||||
#define foreach_css_selector(selector, set) foreach (selector, (set)->list)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user