Now Chromium supports :dir pseudo-class as experimental (--enable-blink-features=CSSPseudoDir) since M89. I actively worked on this feature funded by eyeo. When I was working on :dir pseudo-class on Chromium, it was necessary to solve issues regarding the performance and functionality of existing direction implementations. This posting is about explaining these issues and how I had solved them in more detail. I also had a talk about this at BlinkOn14.
What is directionality?
All HTML elements have their own directionality. Let’s see a simple example.
When we add explicitly a dir attribute to an element like <div dir="ltr">, or in cases where an element that doesn’t have the dir attribute inherits it from its parent that has ltr direction, the element’s directionality is ltr.
When we add explicitly the dir attribute to an element like <div dir="rtl">, or when an element that doesn’t have the dir attribute inherits it from its parent that has rtl direction, the element’s directionality is rtl.
The element’s directionality is resolved through its own descendants, and it is determined as the directionality of the closest descendant that can determine directionality among the descendants. This is usually a character with bidirectional information.
How do elements have directionality in Blink?
Before the element had a caching value for its direction, it depended on the direction property in ComputedStyle, and there were functionality and performance problems.
We didn’t know the directionality if ComputedStyle was not created yet.
We used it with the direction property of CSS in ComputedStyle, but not exactly the same with the element’s directionality.
There were cases when the directionality of the element needed to be recalculated even when there is no change in the element.
We need to recalculate more for :dir pseudo-class.
To solve these problems, we now cache the directionality of the element. We can see the detailed signatures in node.h.
There are the rules to cache the element directionality like
If dir=ltr|rtl, update the directionality of the element and its descendant immediately.
If dir=auto, resolve the directionality and update the element and its descendant immediately.
If no valid dir, use the directionality of the parent before parsing children.
If the child is inserted with no valid dir, use the directionality of the parent.
Complete caching the directionality of all elements before calculating the style.
Note: We have exception handling for the <slot> element to access it via the flattened tree, but it’s still in the middle of the implementation since it is still unclear and under discussion on the Web Spec.
Improved the performance for dir=auto by reducing a calculation of the directionality
Unfortunately, there are no comprehensive measurements of how much performance has improved after caching the directionality of all elements, because it is tricky to measure. However, theoretically, this is clearly a way to improve performance. In addition, a few additional patches had a chance to measure performance and we were able to see improvement. For instance, we do not adjust directionality if the new text’s direction is the same as the old one, or doesn’t have a strong directionality and drop out of the tree walk if the node changed children is passed during traversing. The following results were obtained.