{"id":58,"date":"2021-12-03T04:15:52","date_gmt":"2021-12-03T04:15:52","guid":{"rendered":"http:\/\/blogs.igalia.com\/mshin\/?p=58"},"modified":"2021-12-09T13:20:39","modified_gmt":"2021-12-09T13:20:39","slug":"cache-the-directionality-of-the-html-element","status":"publish","type":"post","link":"https:\/\/blogs.igalia.com\/mshin\/2021\/12\/03\/cache-the-directionality-of-the-html-element\/","title":{"rendered":"Cache the directionality of the HTML element"},"content":{"rendered":"\nNow Chromium supports <code>:dir<\/code> pseudo-class as experimental (<code>--enable-blink-features=CSSPseudoDir<\/code>) since M89. I actively worked on this feature funded by <a href=\"https:\/\/eyeo.com\/\">eyeo<\/a>. When I was working on <code>:dir<\/code> 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.\n\n\n\n\n<h2 class=\"wp-block-heading\">What is directionality?<\/h2>\n\n\n\n\nAll HTML elements have their own directionality. Let\u2019s see a simple example.\n\n\n\n\n<h5>1) LTR<\/h5>\n\n\n\n\nWhen we add explicitly a <code>dir<\/code> attribute to an element like <code>&lt;div dir=\"ltr\"&gt;<\/code>, or in cases where an element that doesn\u2019t have the <code>dir<\/code> attribute inherits it from its parent that has <code>ltr<\/code> direction, the element\u2019s directionality is <code>ltr<\/code>.\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blogs.igalia.com\/mshin\/files\/2021\/12\/ltr-2.png\" alt=\"\" class=\"wp-image-62\" width=\"500px\" srcset=\"https:\/\/blogs.igalia.com\/mshin\/files\/2021\/12\/ltr-2.png 786w, https:\/\/blogs.igalia.com\/mshin\/files\/2021\/12\/ltr-2-580x162.png 580w, https:\/\/blogs.igalia.com\/mshin\/files\/2021\/12\/ltr-2-768x214.png 768w\" sizes=\"(max-width: 786px) 100vw, 786px\" \/><\/figure>\n\n\n\n\n<h5>2) RTL<\/h5>\n\n\n\n\nWhen we add explicitly the dir attribute to an element like <code>&lt;div dir=\"rtl\"&gt;<\/code>, or when an element that doesn\u2019t have the dir attribute inherits it from its parent that has <code>rtl<\/code> direction, the element\u2019s directionality is <code>rtl<\/code>.\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blogs.igalia.com\/mshin\/files\/2021\/12\/rtl-1.png\" alt=\"\" class=\"wp-image-63\" width=\"500px\" srcset=\"https:\/\/blogs.igalia.com\/mshin\/files\/2021\/12\/rtl-1.png 810w, https:\/\/blogs.igalia.com\/mshin\/files\/2021\/12\/rtl-1-580x145.png 580w, https:\/\/blogs.igalia.com\/mshin\/files\/2021\/12\/rtl-1-768x192.png 768w\" sizes=\"(max-width: 810px) 100vw, 810px\" \/><\/figure>\n\n\n\n\n<h5>3) dir=auto<\/h5>\n\n\n\n\nThe element\u2019s 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.\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blogs.igalia.com\/mshin\/files\/2021\/12\/auto.png\" alt=\"\" class=\"wp-image-64\" width=\"510px\" srcset=\"https:\/\/blogs.igalia.com\/mshin\/files\/2021\/12\/auto.png 843w, https:\/\/blogs.igalia.com\/mshin\/files\/2021\/12\/auto-580x299.png 580w, https:\/\/blogs.igalia.com\/mshin\/files\/2021\/12\/auto-768x395.png 768w\" sizes=\"(max-width: 843px) 100vw, 843px\" \/><\/figure>\n\n\n\n\n<h2 class=\"wp-block-heading\">How do elements have directionality in Blink?<\/h2>\n\n\n\n\nBefore the element had a caching value for its direction, it depended on the <code>direction<\/code> property in <code>ComputedStyle<\/code>, and there were functionality and performance problems.\n\n\n\n\n<ul class=\"wp-block-list\"><li>We didn\u2019t know the directionality if <code>ComputedStyle<\/code> was not created yet.<\/li><li>We used it with the direction property of CSS in <code>ComputedStyle<\/code>, but not exactly the same with the element\u2019s directionality.<\/li><li>There were cases when the directionality of the element needed to be recalculated even when there is no change in the element.<\/li><li>We need to recalculate more for <code>:dir<\/code> pseudo-class.<\/li><\/ul>\n\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blogs.igalia.com\/mshin\/files\/2021\/12\/nocache.png\" alt=\"\" width=\"90%\"><\/figure>\n\n\n\nTo solve these problems, we now cache the directionality of the element. We can see the detailed signatures in <a href=\"https:\/\/chromium.googlesource.com\/chromium\/src\/+\/c20225609f324129e99f0cedfc7c9b264059976e\/third_party\/blink\/renderer\/core\/dom\/node.h#908\">node.h<\/a>.\n\n\n\nThere are the rules to cache the element directionality like\n\n\n\n\n<ul class=\"wp-block-list\"><li>If dir=<code>ltr|rtl<\/code>, update the directionality of the element and its descendant immediately.<\/li><li>If <code>dir=auto<\/code>, resolve the directionality and update the element and its descendant immediately.<\/li><li>If no valid <code>dir<\/code>, use the directionality of the parent before parsing children.<\/li><li>If the child is inserted with no valid <code>dir<\/code>, use the directionality of the parent.<\/li><li>Complete caching the directionality of all elements before calculating the style.<\/li><\/ul>\n\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/blogs.igalia.com\/mshin\/files\/2021\/12\/cache.png\" alt=\"\" width=\"80%\"><\/figure>\n\n\n\nNote: We have exception handling for the <code>&lt;slot&gt;<\/code> element to access it via the flattened tree, but it\u2019s still in the middle of the implementation since it is still unclear and under discussion on the Web Spec.\n\n\n\n\n<h2 class=\"wp-block-heading\">Improved the performance for <code>dir=auto<\/code> by reducing a calculation of the directionality<\/h2>\n\n\n\n\nUnfortunately, 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\u2019s direction is the same as the old one, or doesn\u2019t 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.\n\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/chromium-review.googlesource.com\/c\/chromium\/src\/+\/2720084\">in case of replacing the text node<\/a> : 13% \u2b06\ufe0e<\/li><li><a href=\"https:\/\/chromium-review.googlesource.com\/c\/chromium\/src\/+\/2719686\">in case of inserting the text node<\/a> : 270%\u2b06\ufe0e<\/li><\/ul>\n\n\n\n\nYou can also <a href=\"https:\/\/www.youtube.com\/watch?v=VrEP7SPfQVM&amp;list=PL9ioqAuyl6ULbse3njxmvJgJArp_-pKxY&amp;t=2860s\">watch the talk online<\/a> (47:40 min) presented on BlinkOn14.\n\n\n\nI will post about <code>:dir<\/code> pseudo-class when we clarify <code>&lt;slot&gt;<\/code> and support the feature by default on Chromium. Thanks all!\n","protected":false},"excerpt":{"rendered":"<p>Now Chromium supports :dir pseudo-class as experimental (&#8211;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 &hellip; <a href=\"https:\/\/blogs.igalia.com\/mshin\/2021\/12\/03\/cache-the-directionality-of-the-html-element\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Cache the directionality of the HTML element<\/span><\/a><\/p>\n","protected":false},"author":58,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,3],"tags":[5,4,6],"class_list":["post-58","post","type-post","status-publish","format-standard","hentry","category-chromium","category-igalia","tag-blink","tag-chromium","tag-igalia"],"_links":{"self":[{"href":"https:\/\/blogs.igalia.com\/mshin\/wp-json\/wp\/v2\/posts\/58","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.igalia.com\/mshin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.igalia.com\/mshin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.igalia.com\/mshin\/wp-json\/wp\/v2\/users\/58"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.igalia.com\/mshin\/wp-json\/wp\/v2\/comments?post=58"}],"version-history":[{"count":24,"href":"https:\/\/blogs.igalia.com\/mshin\/wp-json\/wp\/v2\/posts\/58\/revisions"}],"predecessor-version":[{"id":95,"href":"https:\/\/blogs.igalia.com\/mshin\/wp-json\/wp\/v2\/posts\/58\/revisions\/95"}],"wp:attachment":[{"href":"https:\/\/blogs.igalia.com\/mshin\/wp-json\/wp\/v2\/media?parent=58"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.igalia.com\/mshin\/wp-json\/wp\/v2\/categories?post=58"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.igalia.com\/mshin\/wp-json\/wp\/v2\/tags?post=58"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}