前端前線 2026 年 10 月 14 日

2026-10-14 — HTML 規格改成邊解析邊消毒,不再先建 fragment

primary=https://github.com/whatwg/html/commit/94857062b437b45c4dc891b130be83b40f7ae999 primary=https://github.com/whatwg/html/issues/12560 primary=https://github.com/whatwg/html/issues/12543

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 未說明對效能的影響,也沒有給出數據。

原始來源:whatwg/html commit 9485706、issue #12560、issue #12543


End of article
0
Would love your thoughts, please comment.x
()
x