HTML 規格改成邊解析邊消毒,不再先建 fragment 再走訪
whatwg/html · 2026-10-13 · commit 9485706
HTML 規格裡的 sanitizer 不再是「先把字串解析成 fragment,再逐節點走訪刪除」的後處理演算法,而是把設定直接交給 HTML parser,在建立與插入節點的當下過濾。獨立的 post-parse「sanitize」演算法被整段移除。
這個變更由 Noam Rosenthal 於 2026-10-13 合併進 whatwg/html,同時關閉 #12560 與 #12543,改動集中在 source 一個檔案,commit 頁面顯示 915 行新增、577 行刪除。
原本的問題
舊流程是先 parse、再 sanitize,所以被丟掉的節點其實已經存在過。#12560 指出,規格裡有一段步驟會在 context element 的 node document 非 inert 時,把節點變成非 inert,結果可能讓圖片開始載入;該 issue 也提到 Gecko 並未照規格走,而是建立 inert 的 DocumentFragment。
另一個問題是串流。#12543 指出 HTML parser 規格本身是串流式的,若 parser 將來提供串流 API,sanitizer 也必須能串流;該 issue 認為可以在 parser 的 tree builder 階段,也就是「creating and inserting nodes」那一步做消毒。這次的改動正是這個方向。
核心改動
sanitizer 設定會被傳進 parser,parser 在每個要建立或插入節點的地方查詢它。commit message 列出的規則如下:
- 不允許的元素不會被建立或插入;或者把插入位置導向「該元素原本會待的位置」,等於用子節點取代它。
- 不允許的屬性在元素建立之前就丟掉。
- 不允許的註解與 processing instruction 直接捨棄。
- 「safe」變體不再是獨立演算法,而是在設定上預先套用額外限制。
| 舊:post-parse | 新:in-parser | |
|---|---|---|
| 被丟棄的元素 | 先建立,再從樹上移除 | 從未建立或插入 |
| 被丟棄的屬性 | 元素建立後再移除 | 元素建立前就不帶 |
| 消毒時機 | parse 完成後另跑一輪 | parser 建立/插入節點時 |
可觀察的行為差異
commit message 明確列出 Web 可觀察的變化,其中最需要注意的是自訂元素。被 sanitizer 丟棄的元素不會有 definition、registry 為 null,所以它們的 custom element constructor 不會執行,也不會因 is 屬性被建立成 customized built-in;消毒期間也不會啟動 speculative fetch。
fragment parsing 在消毒時,會先在 inert document 裡建出結果,再 adopt 進目標文件,因此被丟棄的元素從頭到尾不存在於目標文件。另外,被移除或取代的元素周圍的文字,現在在 parse 時就合併成同一個 Text node。
declarative shadow DOM 也受影響:只有 <template> 與 shadowrootmode 都通過設定,shadow root 才會被附加,<template for> 的 patching 同理。fragment parse 時,最上層的 <template shadowrootmode> 不再對 context element 附加 shadow root。
規格細節
因為 customized built-in 的建立可能執行 script,插入位置改成在元素建立之後才計算。adoption agency algorithm 與 Noah's Ark clause 也同步調整,讓被移除、被取代的元素和被剝掉的屬性不影響它們;後者現在比較的是 token 的屬性,commit message 說這與所有引擎一致。
影響範圍
這是規格層級的合併,各瀏覽器引擎尚需實作,commit 本身未說明任何瀏覽器的出貨時程。以下角色該留意:
- 用 sanitizer 處理使用者輸入、且頁面註冊了 custom element 的網站:不要再假設被過濾的元素「建立過再被拿掉」,它們的 constructor 在新規格下不會跑。
- 測試中斷言 DOM 結構的程式:移除元素後相鄰文字會合併成單一 Text node,
childNodes的數量可能和舊行為不同。 - 使用 declarative shadow DOM 的內容:若設定沒有同時允許
<template>與shadowrootmode,不會得到 shadow root。 - 瀏覽器與 HTML parser 實作者:要把設定查詢嵌進 tree construction,而不是另寫一個走訪器。
此外 commit 未說明對效能的影響,也沒有給出數據。