On 11/11/16 12:22, Manish Goregaokar wrote:
Servo currently has a style tree (stylesheets->rulelist->rules->other
rules and rule lists) in style::Stylesheet[1], and this is shared with
the DOM via Arcs. As I understand it, Gecko, on the other hand, just
uses the CSSOM DOM tree and has no "style tree" otherwise. Reading
rules in Gecko requires traversing through CSSOM objects. This is a
straightforward solution to the same-object restriction; if your style
tree is made up of these objects in the first place there's nothing to
worry about.
Servo can't use this solution. Trying to thread style through the DOM
will mean merging the style and script crates, and it will be quite
complicated to make Servo's style system generic over CSSOM
implementations for stylo to work.
I’ve proposed this approach before, and I don’t think it would be that
complicated. The only parts of components/style that access this tree
(other than the parsing part creating it) is Stylist::update and
Stylist::set_device taking &[Arc<Stylesheet>] and traversing the tree.
I’m sure we can reasonably define a trait to abstract this traversal.
The "leaves" of this tree (selector list, declaration block, …) would
stay in style crate, but the tree structure and the ownership/mutability
story doesn’t need to be handled there.
Bobby argued that we should keep that tree in the style crate because it
can implement some operations that won’t have to be re-implemented in
both Servo and Gecko/Stylo.
But I don’t know if there is much to share anyway, and the alternative
(maintaining parallel trees) also has its complexity.
A possible solution is to have a opaquish DOM backpointer to
corresponding rule objects in the style tree and have it call some
update function to update the DOM when mutating. This isn't a great
solution IMO.
The one that we seem to prefer is maintaining the style tree and the
CSSOM tree in parallel, with references from the CSSOM tree to the
style tree, but not vice versa. Only the DOM mutates the style tree.
Yes, in my mind that was always the plan, as discussed in
https://bugzilla.mozilla.org/show_bug.cgi?id=1281962. Have a tree in
style without parent pointers or pointers back to DOM, and a parallel
CSSOM tree where each JS object holds an Arc to the corresponding style
object (and a parent pointer as needed), with DOM operations taking care
of keeping them in sync.
This could possible be enforced by wrapping all interior mutability in
the style tree with a type that requires a zero-sized token to be
passed in to the borrow_mut/write method; a token which can't be
created normally but can be obtained via a method on dom::Reflectable
(within arms reach for most DOM code). Stylo code can FFI call into
functions using a similar mechanism.
I don’t think enforcing this is important. As mentioned above the part
of the style crate accessing this tree is small, so I don’t think it
likely that it will accidentally mutate it. And I, as far as I know, the
worst that can happen if they do get out of sync is incorrect styling or
results from CSSOM, but nothing like a memory safety issue.
In the case of CSSRuleList, we have a bit of an issue. There's no
corresponding arc'd style:: type for CSSRuleList. There's just
`Vec<style::CSSRule>`, which is used in Stylesheet[1], MediaRule[2],
and @supports rules (not supported in servo yet).
There isn’t yet (in master) but as you did in #14190 the idea is to
introduce Arc’s (and RwLock’s) as needed. (That is, unless we get rid of
this style tree.)
--
Simon Sapin
_______________________________________________
dev-servo mailing list
dev-servo@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-servo