From a90a5cba08fdf6c0ceb95101c275108a152a3aed Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 12 Jun 2024 07:35:37 +0200 Subject: Merging upstream version 127.0. Signed-off-by: Daniel Baumann --- layout/docs/StyleSystemOverview.md | 173 +++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 layout/docs/StyleSystemOverview.md (limited to 'layout/docs/StyleSystemOverview.md') diff --git a/layout/docs/StyleSystemOverview.md b/layout/docs/StyleSystemOverview.md new file mode 100644 index 0000000000..bed5fd057f --- /dev/null +++ b/layout/docs/StyleSystemOverview.md @@ -0,0 +1,173 @@ +# Style System Overview + +## Quantum CSS (Stylo) + +Starting with Firefox 57 and later, Gecko makes use of the parallel +style system written in Rust that comes from Servo. There\'s an +[overview](https://hacks.mozilla.org/2017/08/inside-a-super-fast-css-engine-quantum-css-aka-stylo/) +of this with graphics to help explain what\'s going on. The [Servo +wiki](https://github.com/servo/servo/wiki/Layout-Overview) has some more +details. + +## Gecko + +The rest of the style section section describes the Gecko style system +used in Firefox 56 and earlier. Some bits may still apply, but it likely +needs revising. + +In order to display the content, Gecko needs to compute the styles +relevant to each DOM node. It does this based on the model described in +the CSS specifications: this model applies to style specified in CSS +(e.g. by a \'style\' element, an \'xml-stylesheet\' processing +instruction or a \'style\' attribute), style specified by presentation +attributes, and the default style specified by our own user agent style +sheets. There are two major sets of data structures within the style +system: + +- first, data structures that represent sources of style data, such as + CSS style sheets or data from stylistic HTML attributes +- second, data structures that represent computed style for a given + DOM node. + +These sets of data structures are mostly distinct (for example, they +store values in different ways). + +The loading of CSS style sheets from the network is managed by the [CSS +loader](https://dxr.mozilla.org/mozilla-central/source/layout/style/Loader.h); +they are then tokenized by the [CSS +scanner](https://dxr.mozilla.org/mozilla-central/source/layout/style/nsCSSScanner.h) +and parsed by the [CSS +parser](https://dxr.mozilla.org/mozilla-central/source/layout/style/nsCSSParser.h). +Those that are attached to the document also expose APIs to script that +are known as the CSS Object Model, or CSSOM. + +The style sheets that apply to a document are managed by a class called +the [style +set](https://dxr.mozilla.org/mozilla-central/source/layout/style/nsStyleSet.h). +The style set interacts with the different types of style sheets +(representing CSS style sheets, presentational attributes, and \'style\' +attributes) through two interfaces: +[nsIStyleSheet](http://dxr.mozilla.org/mozilla-central/source/layout/style/nsIStyleSheet.h) +for basic management of style sheets and +[nsIStyleRuleProcessor](http://dxr.mozilla.org/mozilla-central/source/layout/style/nsIStyleRuleProcessor.h) +for getting the style data out of them. Usually the same object +implements both interfaces, except in the most important case, CSS style +sheets, where there is a single rule processor for all of the CSS style +sheets in each origin (user/UA/author) of the CSS cascade. + +The computed style data for an element/frame are exposed to the rest of +Gecko through the class mozilla::ComputedStyle (previously called +nsStyleContext). Rather than having a member variable for each CSS +property, it breaks up the properties into groups of related properties +called style structs. These style structs obey the rule that all of the +properties in a single struct either inherit by default (what the CSS +specifications call \"Inherited: yes\" in the definition of properties; +we call these inherited structs) or all are not inherited by default (we +call these reset structs). Separating the properties in this way +improves the ability to share the structs between similar ComputedStyle +objects and reduce the amount of memory needed to store the style data. +The ComputedStyle API exposes a method for getting each struct, so +you\'ll see code like `sc->GetStyleText()->mTextAlign` for getting the +value of the text-align CSS property. (Frames (see the Layout section +below) also have the same GetStyle\* methods, which just forward the +call to the frame\'s ComputedStyle.) + +The ComputedStyles form a tree structure, in a shape somewhat like the +content tree (except that we coalesce identical sibling ComputedStyles +rather than keeping two of them around; if the parents have been +coalesced then this can apply recursively and coalasce cousins, etc.; we +do not coalesce parent/child ComputedStyles). The parent of a +ComputedStyle has the style data that the ComputedStyle inherits from +when CSS inheritance occurs. This means that the parent of the +ComputedStyle for a DOM element is generally the ComputedStyle for that +DOM element\'s parent, since that\'s how CSS says inheritance works. + +The process of turning the style sheets into computed style data goes +through three main steps, the first two of which closely relate to the +[nsIStyleRule](http://dxr.mozilla.org/mozilla-central/source/layout/style/nsIStyleRule.h) +interface, which represents an immutable source of style data, +conceptually representing (and for CSS style rules, directly storing) a +set of property:value pairs. (It is similar to the idea of a CSS style +rule, except that it is immutable; this immutability allows for +significant optimization. When a CSS style rule is changed through +script, we create a new style rule.) + +The first step of going from style sheets to computed style data is +finding the ordered sequence of style rules that apply to an element. +The order represents which rules override which other rules: if two +rules have a value for the same property, the higher ranking one wins. +(Note that there\'s another difference from CSS style rules: +declarations with !important are represented using a separate style +rule.) This is done by calling one of the +nsIStyleRuleProcessor::RulesMatching methods. The ordered sequence is +stored in a [trie](http://en.wikipedia.org/wiki/Trie) called the rule +tree: the path from the root of the rule tree to any (leaf or non-leaf) +node in the rule tree represents a sequence of rules, with the highest +ranking farthest from the root. Each rule node (except for the root) has +a pointer to a rule, but since a rule may appear in many sequences, +there are sometimes many rule nodes pointing to the same rule. Once we +have this list we create a ComputedStyle (or find an appropriate +existing sibling) with the correct parent pointer (for inheritance) and +rule node pointer (for the list of rules), and a few other pieces of +information (like the pseudo-element). + +The second step of going from style sheets to computed style data is +getting the winning property:value pairs from the rules. (This only +provides property:value pairs for some of the properties; the remaining +properties will fall back to inheritance or to their initial values +depending on whether the property is inherited by default.) We do this +step (and the third) for each style struct, the first time it is needed. +This is done in nsRuleNode::WalkRuleTree, where we ask each style rule +to fill in its property:value pairs by calling its MapRuleInfoInto +function. When called, the rule fills in only those pairs that haven\'t +been filled in already, since we\'re calling from the highest priority +rule to the lowest (since in many cases this allows us to stop before +going through the whole list, or to do partial computation that just +adds to data cached higher in the rule tree). + +The third step of going from style sheets to computed style data (which +various caching optimizations allow us to skip in many cases) is +actually doing the computation; this generally means we transform the +style data into the data type described in the \"Computed Value\" line +in the property\'s definition in the CSS specifications. This +transformation happens in functions called nsRuleNode::Compute\*Data, +where the \* in the middle represents the name of the style struct. This +is where the transformation from the style sheet value storage format to +the computed value storage format happens. + +Once we have the computed style data, we then store it: if a style +struct in the computed style data doesn\'t depend on inherited values or +on data from other style structs, then we can cache it in the rule tree +(and then reuse it, without recomputing it, for any ComputedStyles +pointing to that rule node). Otherwise, we store it on the ComputedStyle +(in which case it may be shared with the ComputedStyle\'s descendant +ComputedStyles). This is where keeping inherited and non-inherited +properties separate is useful: in the common case of relatively few +properties being specified, we can generally cache the non-inherited +structs in the rule tree, and we can generally share the inherited +structs up and down the ComputedStyle tree. + +The ownership models in style sheet structures are a mix of reference +counted structures (for things accessible from script) and directly +owned structures. ComputedStyles are reference counted, and own their +parents (from which they inherit), and rule nodes are garbage collected +with a simple mark and sweep collector (which often never needs to run). + +- code: + [layout/style/](http://dxr.mozilla.org/mozilla-central/source/layout/style/), + where most files have useful one line descriptions at the top that + show up in DXR +- Bugzilla: Style System (CSS) +- specifications + - [CSS 2.1](http://www.w3.org/TR/CSS21/) + - [CSS 2010, listing stable css3 + modules](http://www.w3.org/TR/css-2010/) + - [CSS WG editors drafts](http://dev.w3.org/csswg/) (often more + current, but sometimes more unstable than the drafts on the + technical reports page) + - [Preventing attacks on a user\'s history through CSS :visited + selectors](http://dbaron.org/mozilla/visited-privacy) +- documentation + - [style system + documentation](http://www-archive.mozilla.org/newlayout/doc/style-system.html) + (somewhat out of date) -- cgit v1.2.3