Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upstyle: Make the whole style crate independent of the implementation #9567
Conversation
highfive
commented
Feb 8, 2016
|
Heads up! This PR modifies the following files:
|
highfive
commented
Feb 8, 2016
| if name.chars().all(|c| c.is_lowercase()) { | ||
| Ok(PseudoElement::from(name)) | ||
| } else { | ||
| Ok(PseudoElement::from(&*name.to_ascii_lowercase())) |
This comment has been minimized.
This comment has been minimized.
emilio
Feb 8, 2016
Author
Member
@bholley: Please look at the commit message, do you thing we could do well accepting only names that start with a dash, and it that case assume they are already lowercase?
That should prevent all extra allocs/traversing of the name.
|
Also note that if we're just planning to support the gecko anon-box pseudo-element list, we could keep cc: @SimonSapin |
a86125d
to
754b767
|
Went with the second approach, and saw why both of them needed extra work. Actually I'll need to implement a way of getting matching rules from a I can:
I'd go with the second, but I'd prefer to check-in with Simon in order to confirm that the current approach is correct, and also to discuss a design (in case it is needed) and prevent wasting work. That being said, it's late, he's probably sleeping and I should too, so... enough for today! :P |
Add "before" and "after" atoms. Needed for servo/servo#9567 <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.svg" height="40" alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/string-cache/141) <!-- Reviewable:end -->
| @@ -8,6 +8,73 @@ use selectors::parser::{ParserContext, SelectorImpl}; | |||
| pub enum PseudoElement { | |||
| Before, | |||
| After, | |||
| FirstLine, | |||
|
|
|||
| // https://mxr.mozilla.org/mozilla-central/source/layout/style/nsCSSAnonBoxList.h | |||
This comment has been minimized.
This comment has been minimized.
SimonSapin
Feb 8, 2016
Member
Why is all thing going here rather than in a separate SelectorImpl impl in ports/geckolib? Wasn’t that the point of making the parser generic?
This comment has been minimized.
This comment has been minimized.
emilio
Feb 8, 2016
Author
Member
Yeah, forgot to mention that.
Would it be fine to have a feature-gated gecko selector implementation inside style?
I say it because I tried doing exactly that, and the code is pretty suboptimal (and way less readable).
For example, this:
let map = match pseudo_element {
Some(PseudoElement::Before) => &self.before_map,
Some(PseudoElement::After) => &self.after_map,
Some(_) => &self.other_pseudo_elements_map,
None => &self.element_map,
};Becomes this:
let map = if let Some(pseudo) = pseudo_element {
if pseudo == E::Impl::parse_pseudo_element(&ParserContext::new(), "before").unwrap() {
&self.before_map
} else if pseudo == E::Impl::parse_pseudo_element(&ParserContext::new(), "after").unwrap() {
&self.after_map
} else {
&self.other_pseudo_elements_map
}
} else {
&self.element_map
};
This comment has been minimized.
This comment has been minimized.
SimonSapin
Feb 8, 2016
Member
Would it be fine to have a feature-gated gecko selector implementation inside style?
I’m not opposed but I don’t see how it would help.
Becomes this: [...]
Yes, calling parsing code here is silly. It shows a mis-match between PseudoElement being generic and the before_map and after_map fields of Stylist being hard-coded. I don’t think this means me should abandon the generic parser and have a single PseudoElement type. I’d rather change the way Stylist is organized. Maybe some map of PseudoElement to PerPseudoElementSelectorMap?
This comment has been minimized.
This comment has been minimized.
emilio
Feb 8, 2016
Author
Member
Yes, having a PerPseudoElementSelectorMap per possible pseudo seemed overkill to me, but it might be doable, and it's, in fact, more ellegan than what we have right now.
I can try to do it first and get some numbers if you want.
I was talking about having two different PseudoElement types, as with two different SelectorImpl, but making a default impl feature gated, something like:
enum ServoPseudoElement {
Before,
After,
FirstLine,
}
enum GeckoPseudoElement {
Before,
After,
FirstLine,
// ...
}
struct ServoSelectorImpl;
struct GeckoSelectorImpl;
impl ... for GeckoSelectorImpl { ... }
impl ... for ServoSelectorImpl { ... }
#[cfg(feature = "geckolib")]
pub type DefaultSelectorImpl = GeckoSelectorImpl;
#[cfg(not(feature = "geckolib"))]
pub type DefaultSelectorImpl = ServoSelectorImpl;And we'll ve moving again with concrete types, and would work as long as both implementations have a Before and After variants.
This comment has been minimized.
This comment has been minimized.
SimonSapin
Feb 8, 2016
Member
Re overkill, I’m also open to changing more significantly how Stylist / PerPseudoElementSelectorMap / SelectorMap are organized. (Though I don’t have a specific design in mind right now.)
Re feature-gated impls, ok, I see what you mean. I’m not necessarily opposed to this, but it doesn’t seem nice. I’d like to explore alternatives some more.
|
I'm not happy about parsing pseudo-elements that Gecko doesn't support. |
|
Should be "... that Servo doesn't support". |
|
@Ms2ger same here. This is what I mean by a separate |
|
Could you guys take a quick look at this to see if the current approach is good enough? Right now I've got servo building and working fine (with a rust-selectors update to add the Will like to make a few more tweaks before landing it is it's good though (fnv and trying to not pre-insert elements in the No gecko backend yet, I'll add it when I've got the time :P |
As discussed in IRC while discussing servo/servo#9567
As discussed in IRC while discussing servo/servo#9567
As discussed in IRC while discussing servo/servo#9567
3a82d4b
to
a99959c
1012b26
to
545e884
|
I think this should be mostly ready for landing once servo/rust-selectors#69 lands... r? @SimonSapin (for the style side) Still missing the hability to query on-demand for anon-box pseudo-elements, but I'd prefer to do that as a followup since this is already a pretty decent patch. |
Add Eq and Hash bounds to PseudoElement As discussed in IRC while discussing servo/servo#9567 <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.svg" height="40" alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/rust-selectors/69) <!-- Reviewable:end -->
| let pseudo_element = match_ignore_ascii_case! { name, | ||
| "before" => Before, | ||
| "after" => After, | ||
| "first-line" => FirstLine, |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
emilio
Feb 11, 2016
Author
Member
Sure, sorry! Just parsed it in order to ensure that the problem with the first approaches was solved.
| Some(PseudoElement::After) => &mut after_map, | ||
| let map = if let Some(ref pseudo) = selector.pseudo_element { | ||
| self.pseudos_map.entry(pseudo.clone()) | ||
| .or_insert(PerPseudoElementSelectorMap::new()) |
This comment has been minimized.
This comment has been minimized.
SimonSapin
Feb 11, 2016
Member
Is PerPseudoElementSelectorMap::new() expensive? Maybe use .or_insert_with(PerPseudoElementSelectorMap::new) instead.
This comment has been minimized.
This comment has been minimized.
emilio
Feb 11, 2016
Author
Member
I think it should only be called on the empty case, but or_insert_with is more elegant anyways so I'll change it :P
| V: VecLike<DeclarationBlock> { | ||
| assert!(!self.is_device_dirty); | ||
| assert!(style_attribute.is_none() || pseudo_element.is_none(), | ||
| "Style attributes do not apply to pseudo-elements"); | ||
|
|
||
| let map = match pseudo_element { | ||
| Some(ref pseudo) => self.pseudos_map.get(pseudo).unwrap(), |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
emilio
Feb 11, 2016
Author
Member
That's why we pre-insert the eagerly cascaded pseudos map in the stylist constructor, so yes, this can't fail.
This comment has been minimized.
This comment has been minimized.
SimonSapin
Feb 11, 2016
Member
Can’t this method be called with a non-eagerly-cascaded pseudo-element?
|
|
||
| applicable_declarations.normal_shareable && | ||
| applicable_declarations.before.is_empty() && | ||
| applicable_declarations.after.is_empty() | ||
| applicable_declarations.per_pseudo.values().all(|v| v.is_empty()) |
This comment has been minimized.
This comment has been minimized.
SimonSapin
Feb 11, 2016
Member
We have to be careful here: pseudo-elements that have UA styles with a *|* selector risk defeating style sharing completely.
What pseudo-elements are likely to be in applicable_declarations.per_pseudo at this point? Only the eagerly-cascaded ones?
This comment has been minimized.
This comment has been minimized.
emilio
Feb 11, 2016
Author
Member
Actually there's no support for querying those kind of pseudo-elements, so just the eagerly cascaded ones will be here, which are filled a few lines before.
|
Review status: 32 of 43 files reviewed at latest revision, 8 unresolved discussions. components/layout/traversal.rs, line 32 [r6] (raw file): components/style/restyle_hints.rs, line 83 [r6] (raw file): ports/geckolib/selector_impl.rs, line 17 [r6] (raw file): pub type Stylist = ::style::selector_matching::Stylist; we do pub type Stylist = style::selector_matching::Stylist; That compiles, right? Comments from the review on Reviewable.io |
b5e564a
to
1f7fc58
|
Review status: 27 of 43 files reviewed at latest revision, 7 unresolved discussions. components/layout/traversal.rs, line 32 [r6] (raw file): Thinking about it, most people shouldn't care about the Anyways, that's not near-term, so I plan to land this, and work on querying anon-box pseudos from gecko. Removing the N parameter for now :P ports/geckolib/selector_impl.rs, line 17 [r6] (raw file): Just did that :) Comments from the review on Reviewable.io |
|
|
1f7fc58
to
db7dafd
This commit refactors the style crate to be completely independent of the actual implementation and pseudo-elements supported. This also adds a gecko backend which introduces parsing for the anonymous box pseudo-elements[1], although there's still no way of querying them. https://mxr.mozilla.org/mozilla-central/source/layout/style/nsCSSAnonBoxList.h
The logic was switched between them.
…th a non eagerly-cascaded pseudo-element This actually didn't happen, but this should be done sooner than later.
…option value type. This make the layout code way clearer.
This is unfortunate, but making that useful would require parameterizing `SharedLayoutContext` and `LayoutContext` depending on the `SelectorImpl` (which is a **huge** work right now). Probably the easier way to do it, and probably the one that keeps the layout code more legible, and since there won't be multiple implementations at the same compilation unit, would be "defining" a default implementation for layout via feature flags. That should allow us to remove the components/style/servo.rs file.
db7dafd
to
04d2db5
|
Looks good to me! Thanks for working on this. :-) r=bholley Review status: 19 of 43 files reviewed at latest revision, 5 unresolved discussions. Comments from the review on Reviewable.io |
|
(specifically, on the layout and geckolib stuff. I looked at most of the style stuff, but not all of it, since @SimonSapin was already happy with it). |
|
@bors-servo: r=bholley,SimonSapin |
|
|
…ey,SimonSapin
style: Make the whole style crate independent of the implementation
This allows, among other things, having different implementations for parsing pseudo{elements, classes} in both `ports/geckolib` and in servo.
<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.svg" height="40" alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/9567)
<!-- Reviewable:end -->
|
|
|
@bors-servo: retry (wow, so many intermittents hit this time) |
|
|
|
|
emilio commentedFeb 8, 2016
This allows, among other things, having different implementations for parsing pseudo{elements, classes} in both
ports/geckoliband in servo.