[Перевод] Баг Safari, которого никогда не было

В октябре 2021 года мой коллега-разработчик Иэн опубликовал сообщение в канале поддержки GOV.UK Design System в Slack:

«Интересно, а кто-нибудь заметил, что Safari Technology Preview как-то странно влияет на заголовок, баннер бета-версии и кнопки сайта?»


Safari Technology Preview — это версия браузера Safari для «предварительного ознакомления с будущими веб-технологиями в macOS и iOS». Большинство создателей браузеров предоставляет подобные версии своих браузеров, чтобы разработчики могли тестировать новые функции.

После сообщения Иэна мы посмотрели на Design System в Safari Technology Preview.

4tblgdfabjqj-vzxb6aks2vrnli.png


Мы действительно увидели странное поведение заголовка, баннера бета-версии и кнопок, о которых говорил Иэн. Последнее слово в каждом из этих элементов переносилось на новую строку, хотя это и не было необходимо.

Почему важно было устранить этот баг


Доля Safari на рынке десктопных браузеров составляет примерно 15%. Кроме того, все браузеры в iOS, в том числе Chrome, Edge и Firefox, используют тот же браузерный движок под названием WebKit, который лежит и в основе Safari.

Поэтому если этот баг доберётся до публичного релиза iOS, сайт GOV.UK будет выглядеть так для всех, кто выходит в Интернет через iPhone или iPad, а также для тех, кто пользуется Safari на Mac. Примерно треть всех сессий на GOV.UK проводилась пользователями iOS-устройств.

Разбираемся в баге


Мы хотели сообщить об этом баге команде разработчиков WebKit. Чтобы сделать это, нам нужно дать хорошее объяснение того, что мы наблюдаем, и условий, необходимых для возникновения бага.

Мы могли бы просто создать отчёт о баге с описанием «Какие-то странные вещи происходят в заголовке, баннере и кнопках на сайте GOV.UK в Safari Technology Preview».

Однако по своему опыту мы знали, что чёткое описание бага упростит команде WebKit понимание проблемы, повышая вероятность быстрого устранения бага.

Нам показалось, неплохо будет начать с описания «Перенос текста без необходимости», однако, как ни странно, мы наблюдали эту проблему только на GOV.UK. Другие веб-сайты, в том числе и веб-сайт Национальной службы здравоохранения (NHS) Великобритании, где используется большая часть нашего фронтенд-кода, выглядели нормально.

Путём проб и ошибок (по очереди отключая отдельные функции) мы выяснили, что возникновение проблемы как-то связано со шрифтом. После смены шрифта на Arial проблема исчезла.

re8xpqa98vlkvarakgssbi1fqvc.png


Но даже с этим шрифтом проблема возникала не везде, когда мы изучили различные чекбоксы, текст без необходимости переносился в легенде, в метках каждого чекбокса и в элементе для показа сведений, но не в тексте подсказки.

Мы поняли, что это происходило, когда размер элементов внутренне или выполнялся их автоматический перенос. То есть когда размер элемента определялся его содержимым. Например, когда размер кнопки изменяется, чтобы вместить в себя её текст.

То есть формулировка проблемы такая: «текст с определёнными шрифтами без необходимости переносится в элементах, где размер задаётся внутренне»?

Мы решили, что это хорошее описание проблемы, однако когда попытались создать минимальный пример, то выяснили, что для возникновения проблемы нужно ещё одно условие.

В HTML все дополнительные пробелы (whitespace) между словами игнорируются. То есть можно добавлять дополнительные пробелы или даже новые строки, и это никак не повлияет на то, как текст отобразится в браузере.

Баг возникал, только если в HTML соответствующего элемента где-то присутствовал символ новой строки.

Нам удалось пройти путь от «с заголовком, баннером и кнопками происходит что-то странное» до «при использовании определённых шрифтов текст без необходимости переносится в элементах с размером по содержимому и когда внутренний HTML элемента содержит символ новой строки, которому не предшествует пробел».

Сообщаем о баге


Разобравшись с условиями, необходимыми для возникновения бага, 10 ноября 2021 года мы написали отчёт команде WebKit.

Мы добавили в отчёт страницы, где возникала проблема, версию Safari Technology Preview, в которой, по нашему мнению, впервые появилась проблема, и минимальный набор тестов, демонстрировавший баг.

Спустя несколько дней на отчёт о баге ответил инженер WebKit, написав: «Это очень плохой баг и нам нужно его немедленно устранить».

Проведя расследование, команда внесла в WebKit изменение, устранившее этот баг, а также добавила тест, чтобы этот баг не появлялся в будущем.

К 6 января 2022 года изменение было утверждено и объединено в основную ветвь, а затем включено в Safari Technology Preview 139, выпущенное 26 января.

Причина бага


Возможно, вам любопытно, что же стало причиной бага. Естественно, нам это было интересно, поэтому мы спросили устранившего баг инженера из команды Webkit, сможет ли он провести доклад перед фронтенд-разработчиками нашей компании, на что он любезно согласился.

Он рассказал, что его команда рефакторила код, отвечающий за расположение текста на странице.

Чтобы WebKit мог расположить текст на странице, ему нужно измерить ширину текста. Для этого он использует данные из шрифта, позволяющие определить ширину каждого символа.

8vid8sqfve1wwwvazyerqxbvflw.png


Это включает в себя и ширину whitespace-символов, например, пробелов.

В шрифте также есть данные о символе новой строки, в том числе и его ширина. Но это не имеет никакого смысла — символы новой строки не занимают (или, по крайней мере, не должны занимать) пространства, однако шрифт обращается с ними точно так же, как и с любым другим символом. Автор шрифта всё равно должен указывать в данных шрифта ширину символа новой строки.

А в шрифте, который мы используем на сайте GOV.UK, символ новой строки имеет ширину больше, чем символ пробела, что совершенно необычно.

Код размещения текста в элементах с внутренним переносом состоит из двух этапов: сначала он определяет размер текста и использует это значение для размещения полей в структуре страницы. Затем в качестве отдельного этапа он помещает текст в эти поля. Здесь важно то, что у этих этапов ширина текста должна согласоваться. Баг возникал потому, что согласование между двумя этапами пропадало.

tek1k_06fameixk9ah8g5gzref4.png


Один из них ошибочно использовал в вычислениях ширину символа новой строки, поэтому создаваемое поле оказывалось слишком маленьким.

ngf1f5nng1gvvi4mkohl33vsnwg.png


Этап 1 — число, этап 2 — другое, чуть большее число

На этапе 2, когда WebKit пытался поместить текст в только что созданное поле, он выяснял, что текст не помещается, поэтому последнее слово принудительно помещалось на новую строку.

Мы не выполняли регулярное тестирование с Safari Technology Preview или другими «бета»-версиями браузеров, поэтому стало чистой удачей, что Иэн использовал STP для тестирования чего-то другого.

Насколько нам известно, об этом баге сообщили только мы. Если бы Иэн не потратил своё время, чтобы сообщить об нём в канале поддержки, или если бы у нас не было времени на расследование и отчёт, то с большой вероятностью он бы попал в публичные релизы Safari и iOS.

Это не единственный баг, о котором мы сообщили. За последние несколько лет мы отправили отчёты о более чем семидесяти багах в разных браузерах, отслеживать которые пытаемся при помощи этого проекта на GitHub.

Отправление отчётов о багах разработчикам браузеров — отличный способ помощи в совершенствовании веб-платформы. О том, как отправлять хорошие отчёты по браузерным багам, можно узнать из этой статьи.

© Habrahabr.ru