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 upPseudo element ":before" #1158
Pseudo element ":before" #1158
Conversation
|
You can't add managed boxes to |
| @@ -24,6 +24,7 @@ pub enum PseudoElement { | |||
| After, | |||
| FirstLine, | |||
| FirstLetter, | |||
| none, | |||
This comment has been minimized.
This comment has been minimized.
SimonSapin
Oct 31, 2013
Member
This should not be necessary, as we’re using Option<PseudoElement> everywhere.
| @@ -267,7 +278,7 @@ fn matches_first_child<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: Element | |||
| } | |||
|
|
|||
| #[inline] | |||
| fn match_attribute<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E>, E: ElementLike>( | |||
| fn match_attribute<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E, PseudoElement>, E: ElementLike>( | |||
This comment has been minimized.
This comment has been minimized.
SimonSapin
Oct 31, 2013
Member
Sigh. This is getting out of hand. (Not a criticism of this PR, but we’ll need to get rid of these traits somehow.)
|
|
||
| <%self:raw_longhand name="content" inherited="False"> | ||
| pub use to_computed_value = super::computed_as_specified; | ||
| pub type SpecifiedValue = ~str; |
This comment has been minimized.
This comment has been minimized.
SimonSapin
Oct 31, 2013
Member
Even if no type of value other than is supported yet, this should really be an enum of normal, none, or a list of values.
| #[inline] pub fn get_initial_value() -> computed_value::T { ~"" } | ||
| pub fn parse_specified(input: &[ComponentValue]) -> Option<DeclaredValue<SpecifiedValue>> { | ||
| let mut iter = input.skip_whitespace(); | ||
| match iter.next() { |
This comment has been minimized.
This comment has been minimized.
SimonSapin
Oct 31, 2013
Member
Do not leave the rest of this iterator un-consumed. Properties that only take one value should reject input with more, but in this case this really is a list.
| &self, element: &T, style_attribute: Option<&PropertyDeclarationBlock>, | ||
| pseudo_element: Option<PseudoElement>) -> ~[Arc<~[PropertyDeclaration]>] { | ||
| pub fn get_applicable_declarations<N: TreeNode<T>, T: TreeNodeRefAsElement<N, E, PseudoElement>, E: ElementLike>( | ||
| &self, element: &T, style_attribute: Option<&PropertyDeclarationBlock>) -> (~[Arc<~[PropertyDeclaration]>], ~[Arc<~[PropertyDeclaration]>]) { |
This comment has been minimized.
This comment has been minimized.
SimonSapin
Oct 31, 2013
Member
I disagree with this change of function signature, it doesn’t work as soon as you implement any other pseudo-element. Or do you want the function then to return a bigger data structure with all of them? I’ll need more convincing on why the complexity is better than having this call for each pseudo-element (or none).
| @@ -243,8 +244,10 @@ pub trait TreeNodeRef<Node>: Clone { | |||
| fn is_root(&self) -> bool; | |||
| } | |||
|
|
|||
| pub trait TreeNodeRefAsElement<Node, E: ElementLike>: TreeNodeRef<Node> { | |||
| pub trait TreeNodeRefAsElement<Node, E: ElementLike, PseudoElement>: TreeNodeRef<Node> { | |||
This comment has been minimized.
This comment has been minimized.
SimonSapin
Oct 31, 2013
Member
Is this generic to work around circular dependencies? I’d rather move the PseudoElement enum to libutil.
| pseudo_style: Option<ComputedValues>, | ||
|
|
||
| /// The enum value of pseudo element | ||
| pseudo_element: Option<PseudoElement>, |
This comment has been minimized.
This comment has been minimized.
SimonSapin
Oct 31, 2013
Member
I don’t think that "having a pseudo-element" (and only one!) should be a property of DOM nodes. It’s box/frame generation that checks whether a box should be created for any pseudo-element.
This comment has been minimized.
This comment has been minimized.
parkjaeman
Nov 1, 2013
Author
Contributor
Do you mean that LayoutData of Node should not have the data which decides whether a box for pseudo-element is needed or not?
If so, where do you think the data is included?
This comment has been minimized.
This comment has been minimized.
parkjaeman
Nov 1, 2013
Author
Contributor
Now I am trying to move pseudo node generation from push_node() to construct_recursively() because pseudo element seems to have its own box generator to cover pseudo element with display = block. In current design, pseudo element with display = inline is only considered.
This comment has been minimized.
This comment has been minimized.
parkjaeman
Nov 2, 2013
Author
Contributor
I moved pseudo element creation from original location of render box creation to location of box generator creation. Then, current design can cover pseudo element of which display value is block as well as inline.
|
Sorry, but I believe that this patch in 9450e0d has not just minor issues to fix, but the whole design should be revised. In particular, a DOM not does not have a single optional pseudo-elements, but box generation may be affected by a number of pseudo-elements on each element. Also, I’m not convinced that the style system should handle all declarations for an element and its pseudo-elements at the same time, rather than having the caller request styles for a given pseudo-element (or none for the element itself.) |
|
please rebase it |
|
We are doing rebase now |
|
We finished rebasing our code. |
This comment has been minimized.
This comment has been minimized.
jdm
commented on src/components/script/dom/node.rs in ee54f63
Nov 8, 2013
|
Is it possible for script to access pseudo elements/text? These nodes won't have JS wrappers right now, which sounds bad to me. |
|
@jdm In current design, script does not access to pseudo element. As we know, such design is conforming with CSS 2.1 specification. Please check the sentence "Neither pseudo-elements nor pseudo-classes appear in the document source or document tree." in 5.10 Pseudo-elements and pseudo-classes. |
|
@jdm getComputedStyle takes an optional argument to access style of pseudo-elements, but there is no DOM node for pseudo-elements. So there is access to the "content" property, but I don’t know a way to access the actual generated text. |
|
r? @SimonSapin |
Also, I’m less familiar with box generation code and I would appreciate someone else to review that part :) |
|
I am worried about the layout-created nodes sitting inside the script-created nodes. When the script task GCs the script nodes, we will end up freeing layout boxes in the script task, which has caused crashes before. |
|
I’m not convinced that pseudo-elements should be DOM nodes at all. My mental model is that one element (DOM node) creates more than one CSS box. |
|
@SimonSapin "In style/selector_matching.rs, same comment as earlier: The get_applicable_declarations function used to take an optional pseudo_element parameter, indicating which styles should be returned. You change it to not take that parameter, and have it return both "normal" and pseudo-element style. Is this only for the ::before pseudo-element? How will this work when more pseudo-elements are supported, return a more complex data structure? How is this better than the previous design?" Do you think that get_applicable_declarations() has to be called in main/css/matching.rs:match_node() for normal style and all kinds of pseudo element. In that case, we have to call get_applicable-declarations() 5 times for each element, if we consider 4 pseudo elements(first-line, first-letter, before and after), although most element does not include pseudo element. Then, matches_selector() in get_applicable_declarations() has to call 5 times than current design on my pull request where matches_selector() is called just one time for each element & for each rule. Hence, I propose following two approaches, First, the function get_applicable_declarations() is modified to return a vector of applicable_declarations where length of the vector is same with pseudo element's number plus 1. Second, we transfer match_node() into style/selector_matching.rs and merge the function with get_applicable_declarations(). How do you think about those approach? |
|
I asked Boris for his thoughts on using actual DOM elements:
|
|
For the parsing of the 'content' property, please use SimonSapin@b64bfbe . In addition to whitespace and naming it parses the "normal" and "none" values, and returns Regarding selector matching:
Yes, that is the design I had in mind. Note that before your changes, the first thing
If you’re worried about the cost of doing multiple stylesheet traversal per element (ever though the cost of each step is small), I could agree with your idea of having I am very much against using a vector where each index has a special meaning. Please use a struct with fields like
With the current crate dependency graph, that would mean adding a lot to the traits for the DOM tree in the util trait, and probably worsening the What would be the benefit? |
|
Also, I would like someone else to review the DOM and box generation parts of this. |
| @@ -175,9 +181,13 @@ impl<View> TreeNodeRefAsElement<Node<View>, Element> for AbstractNode<View> { | |||
| fn with_imm_element_like<R>(&self, f: &fn(&Element) -> R) -> R { | |||
| self.with_imm_element(f) | |||
| } | |||
| fn set_pseudo_element(&mut self, pseudo_element: Option<PseudoElement>) { | |||
This comment has been minimized.
This comment has been minimized.
jdm
Dec 10, 2013
Member
This should be implemented on the Node<LayoutView> type; script should not be able to acces the layout data.
| @@ -484,6 +494,12 @@ impl AbstractNode<ScriptView> { | |||
| } | |||
| } | |||
|
|
|||
| impl<View> AbstractNode<View> { | |||
This comment has been minimized.
This comment has been minimized.
|
Just saw this.
It should be relatively easy to refactor flow construction to handle both "real" nodes and generated content, BTW. Traits for the win :) |
|
Related to issue #805 |
|
For matching, another option would be to separate the selectors into "buckets" (eg. different This or the PR’s current approach of returning a big data structure both work, so I suggest doing whatever is more convenient for layout code. |
|
For what it's worth, what Gecko does is to have a separate RuleHash per pseudo-element. |
|
@SimonSapin First, all pseudo-elements have its own stylist like follows. struct LayoutTask { Second, all pseudo-elements have one new stylist which covers all pseudo-elements like follows. struct LayoutTask { Third, all pseudo-elements share the existing stylist which need to be modified to cover pseudo element like follows. struct LayoutTask { where struct PerOriginSelectorMap { struct PseudoElementSelectroMap { Happy new year :) |
|
@parkjaeman Yes, I believe we understand each other :) The PR currently does something like your third, and I suggest it could do something like your first if that’s more convenient for layout code. |
|
The Selector matching and cascading parts of this have been merged in #1464. What’s remaining is box generation. |
|
Has this been superseded by #1158? |
|
Is there any reason to leave this one open right now? |
|
@jdm It is OK to close this PR. |
Cleanup document.getElementsByName-null-undef.{html,xhtml}.
parkjaeman commentedOct 31, 2013
This pr is regarding to implementation of pseudo element.
To make pseudo element work normally, we invalidated a assert which is "assert!(style_attribute..." in selector_matching.rs. From the assertion, servo crashes on all the test case with inline style.
Credit with ILyaon.