blog
blog copied to clipboard
Servo 的 style 系统
Servo 的 style 系统
- selector 的实现
- style 系统通用了很多东西,为了能和 Servo 的 layout 系统、Stylo 共享(Stylo 项目旨在把 Servo 的 style 系统集成到 Gecko 中)
- 主要的通用特性是选择器的 SelectorImpl,这里有解析伪元素和其它伪类的所有逻辑。对应的规范是 Selectors Level 4 / Tree-Structural pseudo-classes
- Servo 扩展了这一特性,以便在 Stylo 和 Servo 间分享更多的东西
- 主要的 Servo 实现(用在常规构建中)是 SelectorImpl
- DOM glue(胶水)
- stylelist
- stylelist 结构保存文档的所有选择器和设备特征
- 样式表的 CSS 规则被转成 Rule,并根据伪元素(见 PerPseudoElementSelectorMap)、样式表的来源(见PerOriginSelectorMap)和优先级(见PerOriginSelectormap的
normal
和important
字段),将其引入到 SelectorMap - 每个 pipeline 创建一次 stylelist 结构,在该管道对应的 LayoutThread 中
- properties 模块
- properties 模块是一个 mako 模板,所有 properties、computed value 的计算和层叠逻辑都在那
- 它是一个包含大量代码的复杂模板。主函数是 cascase 函数,这里执行所有计算
- 伪元素的处理
- 介绍
- 伪元素是 style 系统中棘手的一块。并非所有的伪元素都非常常见,因此有些伪元素可能会跳过层叠
- 截止目前,Servo 有五个伪元素
- ::before 和 ::after
- ::selection
-
::-servo-details-summary
-
::-servo-details-content
- 两个
::-servo-details-
伪类都是私有的,i.e. 它们只解析来自 User-Agent 样式表里的 - Servo 有三个不同的方式去层叠伪元素,它们定义在 PseudoElementCascadeType
- Eager 层叠
- 这个模块计算 computed values 给定节点的伪类,通过 style 系统的第一个 pass
- 这用于所有的伪类元素,到目前为止,它是唯一方式一个公共的伪元素应该被层叠(关于它的解释见下方)
- Precomputed 层叠
- 根本就没有层叠。被标记为这样的伪元素不被层叠
- 应用于这类伪类元素的唯一规则是全局规则(
*|*
选择器的规则),它们被直接应用到元素的 style,如果展示 -
::-servo-details-content
是这种伪类元素的一个例子,在 UA 样式表中的所有规则-有选择器*|*::-servo-details-content
(也仅有这些)被评估通过元素的style(除去display
的值,那会被layout重写) - 私有伪类元素的首选类型(尽管它们中的而一些可能需要选择器,往下看)
- Lazy 层叠
- Lazy 层叠允许懒计算伪元素的样式,即,仅在需要的时候才会计算
- 目前(对于 Servo,对于 stylo 而言不是那么多),支持这种伪元素的选择器只是可以在布局树上匹配的选择器的子集,它不能保存来自 DOM 树的所有数据
- 该子集包括标签和属性选择器,足以制作
::-servo-details-summary
lazy伪元素(关于它,只需要知道它是否在open
细节元素中) - 由于没有其他选择器适用于它,这(至少现在)不是公共伪元素的可接受类型,但应考虑用于私有伪元素
- 介绍
https://github.com/servo/servo/blob/master/docs/components/style.md
Servo 中的 Crates #10
- crate style
- crate cssparser