This is basically the gist of a discussion that I and xidorn were
having, pertaining to CSSOM in both Servo and Stylo. We mostly wrapped
it up, but there are loose ends and I'm not sure if the choices made
are correct.

In CSSOM, you basically have a StyleSheetList holding many StyleSheets
holding a CSSRuleList holding many CSSRules. You can
index/insert/delete on the lists and CSSRule can be manipulated in a
bunch of ways.

One invariant that's not *exactly* specified by the spec (but is sort
of hinted at, and implemented by browsers) is that these lists should
yield the same underlying JS object when you access the same
conceptual rule/stylesheet in a list (even if the rest of the list was
mutated). So the DOM indexing methods cannot just create
rule/stylesheet JS objects on the fly, they need to cache them somehow
and update them when the list is updated.

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.

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.
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.

So far this seems good (though very open to other ideas or suggestions
for improvement).

However, in this model the DOM still needs to hold Arcs to the
corresponding style system objects. In some cases, this is
straightforward. dom::StyleSheet holds an arc to a style::Stylesheet.
dom::CSSRule contains a style::CSSRule (which is a cheaply cloneable
enum of Arcs).

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).

Now, we could just put the Vec in an Arc. I'm not sure if we want to
with the extra indirection, but it's a simple solution. An alternative
is to recognize that the `Vec<CSSRule>` is always going to be stored
within larger Arc'd objects, and just use those, by storing an

enum RuleListOwner {
    Sheet(Arc<Stylesheet>),
    Media(Arc<MediaRule>),
    // ..
}

This is great for the Rust code -- easy to abstract over and no extra perf cost.

However, this can't be easily passed over to C++ for stylo. There's no
way to write a corresponding C++ type that takes up the same
space/alignment as a Rust enum. We could hardcode the size and have
sizeof assertions in the tests, but that may not solve alignment
issues, especially with the unspecified Rust ABI. We could also store
an explicit tag/pointer pair which we have unsafe wrappers for on the
Rust side. Ick.

Personally I think just sticking the vec into an Arc is fine and won't
impact us much. But I don't know.

Overall, I think we need to map out the ownership graph of CSSOM in
both Servo and Stylo before starting work on it.


[1]: https://doc.servo.org/style/stylesheets/struct.Stylesheet.html
[2]: https://doc.servo.org/style/stylesheets/struct.MediaRule.html

Thanks,
-Manish Goregaokar
_______________________________________________
dev-servo mailing list
dev-servo@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-servo

Reply via email to