HTML解析是一個將字節轉化爲字符,字符解析爲標記,標記生成節點,節點構建樹的過程。html
是詞法分析過程,將輸入內容解析成多個標記。HTML標記包括起始標記、結束標記、屬性名稱和屬性值。標記生成器識別標記,傳遞給樹構造器,而後接受下一個字符以識別下一個標記;如此反覆直到輸入的結束。算法
該算法的輸出結果是 HTML 標記。該算法使用狀態機來表示。每個狀態接收來自輸入信息流的一個或多個字符,並根據這些字符更新下一個狀態。當前的標記化狀態和樹結構狀態會影響進入下一狀態的決定瀏覽器
在樹構建階段,以 Document 爲根節點的 DOM 樹也會不斷進行修改,向其中添加各類元素。併發
標記生成器發送的每一個節點都會由樹構建器進行處理。規範中定義了每一個標記所對應的 DOM 元素,這些元素會在接收到相應的標記時建立。這些元素不只會添加到 DOM 樹中,還會添加到開放元素的堆棧中。此堆棧用於糾正嵌套錯誤和處理未關閉的標記。其算法也能夠用狀態機來描述。這些狀態稱爲「插入模式」。spa
<html> <body>hello</body> </html>
標記化code
初始狀態是數據狀態。htm
遇到字符 < 時,狀態更改成「標記打開狀態」
。接收一個 a-z字符會建立「起始標記」
,狀態更改成「標記名稱狀態」
。這個狀態會一直保持到接收> 字符。在此期間接收的每一個字符都會附加到新的標記名稱上。在本例中,咱們建立的標記是 html 標記。對象
遇到 > 標記時,會發送當前的標記,狀態改回「數據狀態」
。 標記也會進行一樣的處理。目前 html 和 body 標記均已發出。如今咱們回到「數據狀態」。接收到 Hello world 中的 H 字符時,將建立併發送字符標記
,直到接收</body> 中的<。咱們將爲 Hello world 中的每一個字符都發送一個字符標記。token
接收</body> 中的<,如今咱們回到「標記打開狀態」
。接收下一個輸入字符 / 時,會建立 end tag token 並改成「標記名稱狀態」
。咱們會再次保持這個狀態,直到接收 >。而後將發送新的標記,並回到「數據狀態」
。 輸入也會進行一樣的處理。事件
樹構建
樹構建階段的輸入是一個來自標記化階段的標記序列
第一個模式是「initial mode
」。
接收 HTML 標記後轉爲「before html
」模式,並在這個模式下從新處理此標記。這樣會建立一個 HTMLHtmlElement 元素,並將其附加到 Document 根對象上。
而後狀態將改成「before head
」。此時咱們接收「head」標記。即便咱們的示例中沒有「head」標記,系統也會隱式建立一個 HTMLHeadElement,並將其添加到樹中。
如今咱們進入了「in head
」模式,
而後轉入「after head
」模式。系統對 body 標記進行從新處理,建立並插入 HTMLBodyElement,
同時模式轉變爲「body
」。如今,接收由「Hello world」字符串生成的一系列字符標記。接收第一個字符時會建立並插入「Text」節點,而其餘字符也將附加到該節點
接收 body 結束標記會觸發「after body
"模式。如今咱們將接收 HTML 結束標記,
而後進入「after after body
」模式。接收到文件結束標記後,解析過程就此結束。解析結束後的操做
當HTML解析完成後,瀏覽器會將文檔標註爲交互狀態,並開始解析那些處於「deferred」模式的腳本,也就是那些應在文檔解析完成後才執行的腳本。而後,文檔狀態將設置爲「完成」,一個「加載」事件將隨之觸發。