Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ブラウザの作り方

 ブラウザの作り方

Keiya Sasaki

January 25, 2021
Tweet

More Decks by Keiya Sasaki

Other Decks in Technology

Transcript

  1. 実装状況
 • display … block, inline • background, color •

    width, height, margin, border, padding • font-family(local fontのみ) • font-size, font-weight, font-style • line-height • Scroll • Text周り(改行など)
  2. ブラウザの仕組みを知る
 • Populating the page: how browsers work
 ◦ こっちはブラウザの詳しい説明というよりはWeb

    Performanceを中心にして 
 ブラウザの仕組みを解説している 
 ◦ 最初にこっちを読むと下の記事が読みやすいかも 
 • How Browsers Work: Behind the scenes of modern web browsers
 ◦ Parserの仕組みからブラウザの詳細な仕組みについて解説している 
 

  3. ブラウザを作る
 • Let's build a browser engine! を読む
 ◦ Servoのメンバーの人が書いた記事

    
 ◦ Rustを使って実装していく
 ◦ Part1 ~ Part7まである
 ◦ 機能を絞っているので、テンポ良く実装できる 
 ◦ HTML・CSS のParse → Style → Box Model → Layout → Paint 
 ◦ Paint部分は画像として出力している 
 • W3C を読む
 ◦ CSSなどの仕様
 • WHATWG を読む
 ◦ DOM, HTMLなどの仕様

  4. 仕様の読み方(W3C)
 • Jxckさんの WEB技術の調査方法 の W3C/WHATWG のセクションを
 読むと読み方がわかってくる
 • W3Cの

    Levels, snapshots, modules… を読むと、どのように仕様が
 策定されていくかがわかる

  5. 参考になるリポジトリ
 • Servo
 ◦ `/components` 配下に各moduleが入っている
 • twilco/kosmonaut 
 ◦

    Servoをインスパイアしたブラウザエンジン 
 ◦ Let's build a browser engine!を参考にしている
 ◦ parserとかはservoで使われているparserを使っている 
 • maekawatoshiki/naglfar
 ◦ 日本人の方が作っているブラウザ 
 ◦ Let's build a browser engine!を参考にしている
 • keiya01/kamaitachi
 ◦ 今作っているやつ

  6. ブラウザの仕組み
 Parse
 Style
 Layout
 Paint
 HTML・CSSを Tree構造のデー タに変換する
 CSSルールをDOM と紐付ける(レン

    ダーツリー)
 Styleをもとに、
 それぞれの要素の Positionや高さ、
 幅を計算していく
 Layoutで計算した データをもとに
 描画していく

  7. HTML Parse
 1. 1文字づつプログラム中の文字を読み込んでいく
 2. `<`が見つかったら、elementとして、タグの中身を読み取っていく
 ◦ `<div></div>`の場合、`<`が見つかると、中身を1文字づつ`>`にぶつかるまで 
 探索していく


    3. `<..>`の中身を読みよったら、次に子要素を読み取っていく
 ◦ `<div><p>children</p></div>`の場合、`<p>`を同じように読み取っていく 
 4. 子要素を読み取ったら最後に`</`があるかを確認する
 ◦ HTMLは後方互換性のために基本的に構文エラーは起きない 
 ◦ そのため、`</`がなかったとしてもそのまま処理を続ける 
 5. Text Nodeが存在する場合は、`<`に達するまで文字を読み取っていく

  8. CSS Parse
 1. 先頭に`.`が見つかればclass、`#`が見つかればid、使用可能な文字列であれば
 要素名としてparseし、selectorsに格納する
 2. `{`にぶつかると宣言ブロックの処理に移る
 3. ここでは`property: value;`のペアをそれぞれparseし、declarationsに格納する


    4. CSSには詳細度(specificity)という、どのCSSルールを適用するかを決める
 重み付けのようなものがあるのでそれを求める
 ◦ idをselectorに持つ宣言はclassよりも優先されるといったようなもの 
 5. 詳細度をもとにselectorsをsortしておく

  9. Style
 1. HTMLのparseで得たDOMとCSSのparseで得たCSSOMを
 Root Nodeから順に見ていく
 2. CSSのRulesは詳細度によってsortされているので、
 NodeとSelectorが最初にmatchした要素を取得する
 3. matchしたCSS

    Rulesを詳細度の低いものから高いものへソートし、
 HashMapにpropertyをkeyとしてvalueをinsertしていく
 ◦ これにより、先にinsertされた値は、後にinsertされる詳細度の高い値で 
 上書きされる
 4. ここでは省略するが、他にもUseragent Stylesheetとのmergeや、
 継承、computed valueなどの処理もここで行う

  10. Layout
 1. StyleTreeからdisplayの値を受け取り、Box(display)ごとに分類する
 ◦ BlockNode, InlineNode, TextNodeなど 
 ◦ 分ける理由は、Boxによってpositionが異なるから

    
 ◦ 例えば、Blockは縦方向に配置されるが、Inlineは横方向に配置される 
 2. BlockNodeの場合、width => position => children => heightの順で
 計算していく
 3. InlineNodeの場合は、扱い方が2種類ある。
 ◦ BlockNodeの中にInlineNodeのみが含まれている場合(<span>abc<em>def</em></span>) は、そのまま処理を進める
 ◦ BlockNodeの中にInlineNodeとBlockNodeが含まれている場合、各Boxは同じTypeのBoxし か含めることができないので、InlineNodeをAnonymouseBlock 
 というBoxでラップする。これにより横に配置する処理を行いやすくする。 

  11. Paint
 1. 最初にLayout TreeからDisplayListを作成する
 ◦ DisplayListはbackground-colorやcolorなどの情報を切り出しておき、 
 レンダリング処理を行いやすくする 
 ◦

    DisplayListとして切り出しておくことで、colorの変更などが起こったときに、DisplayListを 探索すれば簡単にcolorの変更ができたりする 
 2. DisplayListからItemを取り出し描画していく