Хабрахабр

[Из песочницы] Newtoo — разработка полноценного браузерного движка с нуля в 2018?

image

Меня зовут Дмитрий Козичев. Привет!

Сегодня я вам расскажу о моей попытке создать собственный современный веб-браузерный движок с нуля.

Мой движок называется Newtoo.

Что за Newtoo

Итак, Newtoo. Зачем я его создал?

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

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

Идеология Newtoo — показать страницу быстрее, чем остальные.

Как я говорил ранее, основные браузерные движки развиваются не первый год. Те ошибки, которые были допущены на начальных стадиях разработки остаются в проекте до конца. Самый яркий пример этому — умные указатели в C++ — это еще более сложный синтаксис, большой оверхед при работе, создании и удалении умных указателей. Кроме того, есть очень много типов умных указателей и нужно знать, какой когда использовать, ведь у каждого есть свои сюрпризы ньюансы. Посмотрите на этот файл из WebKit. Когда видишь такой код, синтаксис умных указателей, пытаешься успокоится и дышать ровно, но такого рода код — это весь вебкит с ног до головы. В моем движке нет таких недостатков.
Давайте посмотрим из чего состоит Newtoo

На данный момент реализованы следующие части проекта:

  • Парсер HTML
  • Сериализатор HTML
  • Парсер CSS (селекторы, правила и свойства)
  • Сериализатор CSS
  • Основное DOM API1

Остальные части проекта, которые пока не реализованы:

  • Каскадинг CSS (вычисление css стилей)
  • Компоновщик
  • Рендер
  • Виртуальная машина JS и события
  • Обработчик событий и интерактивное выделение страницы

Парсер HTML

Мой парсер HTML вполне можно назвать современным. Начнем с того, что он построен по стандарту HTML5. Он учитывает любую вашу ошибку.

Например, вы забыли поставить кавычки, набирая атрибут

<article id=hello></article>

Движок вас поймет, есть значение атрибута написано без пробелов

Вы можете не закрывать тег, когда это не обязательно


<div> <p>First line <p>Second line <img src="ru/images/2019.png" alt="С новым годом!"> <p>Third line <br> Last line
</div>

Парсер поддерживает префиксы


<myprefix:span>Hello, world!</myprefix:span>

Для того, чтобы обратно превратить элементы страницы в код, я написал сериализатор HTML. Я думаю, вы догадались, что он делает.

Как работает парсер HTML

Для начала наш парсер режет наш html код на кусочки и определяет их тип.

К примеру вот это:


<!doctype html><html><head><title>Lorem ipsum</title></head></html>

Превращается в это:


<!doctype html> - doctype token
<html> - tag token
<head> - tag token
<title> - tag token
Lorem ipsum - text token
</title> - close tag token
</head> - close tag token
</html> - close tag token

Эти кусочки называются токены.

Токены делятся на 6 типов:

  • Тег
  • Закрывающийся тег
  • Текст
  • Комментарий
  • Тип документа (doctype)
  • Javascript или css код

Парсер читает токены слева направо. Для каждого типа свой подход парсинга.

Когда парсер читает содержимое тега, сам тег регистрируется в иерархии (иерархия от ребенка до родителя вниз), а когда парсер закончил читать содержимое тега, он удаляет его из иерархии.

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

Используя такой метод парсинга токенов, можно писать <p> без закрывающегося тега.

Парсер CSS

На данный момент движок умеет парсить только стилевые css правила, например:

.flex[alignment="right"]

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

В отличии от других движков, Newtoo поддерживает одиночные комментарии '//' в css коде и не удаляет их при взаимодействии с css через javascript.

Парсер CSS селекторов

Чтобы узнать, какие именно html элементы страницы нужно форматировать стилями css, был придуман язык селекторов. Вы наверное его уже знаете.

Парсер селекторов поддерживает все комбинаторы, два вида кавычек, селекторы тегов, классов, атрибутов, множественные селекторы и классы.

Вот полный список всех поддерживаемых селекторов:

TagName
#Id
.Class
[attr=value]
[attr|=value]
[attr$=value]
[attr~=value]
[attr^=value]
[attr*=value]
.Multi.Class
#Mix#ed.Selec[tor=s] "Quotes" 'Alternative quotes'
#descedant #child
#parent < #child
#previous + #this
#other ~ #this
.multi, .selectors
#element:hover
#element:active
#element:...

Да, селекторы четвертого уровня движок пока не поддерживает, но я работаю на этим.

DOM API

Когда мой парсер HTML читает наш код, он создает объектную модель документа (DOM). DOM выглядит как дерево из узлов, где корень — окно браузера, от него ответвляется документ, а от документа уже элементы страницы. Cо всеми узлами DOM можно взаимодействовать через JavaScript c помощью DOM API.

Например, можно переделать html код любого элемента: Мой движок поддерживает любые изменения изменения DOM.

document.getElementById("article").innerHTML = "Статья исчезла. <b>Бум!</b>";

Сейчас не буду перечислять все функции работы с элементами, документом, текстом, выделением, поверьте, их много!

Виртуальную машину JavaScript пока не написал, но API уже есть и хорошо работает.

Будущее проекта

Про перспективы проекта ничего не могу сказать, вам решать.
Если вам понравился мой движок, значит я хорошо постарался.

Newtoo на GitHub

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть