iframe/frame 插入時 javascript: URL 的 load 事件修正
WHATWG HTML spec commit · 2026-09-28
動態插入的 iframe,如果 src 是一個不會產生新文件的 javascript: URL(例如指令執行後沒有回傳字串),瀏覽器實際上會停留在插入當下自動建立的「初始 about:blank」文件上,但 WHATWG HTML 規格文字卻讓這種情況永遠觸發不了 load 事件。WHATWG HTML 在 commit cbc0d17(2026-09-28,作者 shannonbooth)修正了這個時序缺陷,同時修好 frame 元素被誤套用 iframe 專屬載入步驟的另一個錯誤。
背景
依照較早的 PR #6869 定下的規則,任何 iframe/frame 插入 DOM 時都會先「同步」建立一份初始 about:blank 文件,讓 contentDocument 立刻可用,不必等真正的網路請求完成。這份初始 about:blank是規格特別為了對齊既有實作而設計的暫時文件——Chrome、Safari 在插入當下就同步跑完 load 事件,Firefox 則是非同步觸發。
當 src 屬性指向 javascript: URL 時,這段程式碼執行後不一定會回傳字串;不回傳字串就不會產生新的 Document,框架會停留在初始 about:blank 上,不會發生一般認知裡的「導覽」。但對頁面來說這仍然是一次「載入完成」——瀏覽器實際觀察到的行為,是 iframe 內容從無到有地穩定下來,理當觸發一次 load。規格用一個叫 initialInsertion 的旗標,判斷此時是否該補發這個事件,好讓開發者掛的 onload handler 不會永遠等不到觸發,這也是為什麼這個看似冷門的 javascript: src 寫法,會被規格單獨拉出來處理的原因。
規格細節
問題出在「處理 iframe 屬性」(process the iframe attributes)這一步呼叫「導覽 iframe 或 frame」(navigate an iframe or frame)演算法時,根本沒有把 initialInsertion 傳進去,導致條件式永遠判斷為 false,load 事件永遠不會補發。frame 元素這邊則是另一種錯位:呼叫時把 initialInsertion 誤塞進 srcdocString 的參數位置,而且原本的「導覽至 javascript: URL」步驟不分青紅皂白地一律呼叫 iframe load event steps,但那組步驟是 iframe 元素專屬的內部狀態機,套用在 frameset 底下的 frame 元素上並不成立。
<li><p>If initialInsertion is true, container is non-null, and
targetNavigable's active document's is initial about:blank is true:</p>
<ol>
<li><p>If container is an iframe element, then run the iframe
load event steps given container.</p></li>
<li><p>Otherwise, fire an event named load at container.</p></li>
</ol>修好之後,兩處呼叫都補上了正確的參數:「處理 iframe 屬性」把 initialInsertion 傳進「導覽 iframe 或 frame」,「處理 frame 屬性」則把它塞回正確的位置,並多加一個 null 參數對齊新的函式簽名。判斷分流也同時補上:先看 container(也就是實際的 DOM 元素)是不是 iframe,是的話才跑 iframe 專屬的 load event steps;如果是 frame,改成直接對它 fire 一個普通的 load 事件。規格也順手補了一條 note,說明 container 可能因為 Trusted Types 的 default policy,或是 javascript:frameElement.remove() 這類自砍自身的程式碼而變成 null。
影響範圍
這次修正影響的是規格文字與瀏覽器實作行為對齊的問題,而不是新增能力:Chromium、WebKit 等引擎原本就會在插入含 javascript: src 的 iframe 時同步觸發 load,只是規格描述漏掉了 initialInsertion 這個參數,讓依規格重新實作的引擎(或未來的新引擎)可能做出不同結果,也讓想靠規格文字驗證瀏覽器行為是否正確的測試作者無所適從。
對前端開發者來說,實際會踩到這條邊界情況的通常是用 javascript: URL 當 iframe/frame 佔位符的舊程式碼,例如 <iframe src="javascript:void(0)">,或是框架庫用來建立沙箱環境的技巧;這類元素上掛的 onload handler,在符合規格的實作裡現在能確定會被觸發,不用再額外加 timeout 補救,也不用擔心切換到 frame 元素時事件行為不一致。
這次修正也附上對應的web-platform-tests 測試(wpt#62993),瀏覽器廠商可以直接拿來驗證自家實作是否符合新規格文字;commit 訊息標明這是 #12978 與 #12959 的後續修正,代表 initial about:blank 與 javascript: URL 交互這塊,近期仍在持續補洞。
原始來源:WHATWG HTML commit cbc0d17、web-platform-tests/wpt#62993