Bun 為 JavaScriptCore 實作共享記憶體多執行緒,單體 JS 堆積跨核心直接共用
oven-sh/WebKit · GitHub Pull Request #249 · 2026-06-20
Bun 的 WebKit fork 在 2026 年 6 月以一個 約 66,000 行的超大型 PR 提出 JavaScriptCore 原生共享記憶體多執行緒機制,允許多條 JS 執行緒不經序列化而直接讀寫同一個物件堆積。這份 PR 標號 #249,由 Bun 核心團隊主導,是目前 JS 引擎在真正平行運算方向最激進的嘗試之一。PR 本身明確聲明此功能尚未完成,也可能永遠不合併,但其技術設計文件極為詳盡,已成為 JS 並發討論的重要參考。
為什麼 Web Workers 還不夠?
現行 Web 平台的 Worker 模型採用獨立堆積加上結構化複製(structured clone)來傳遞資料,每次跨執行緒溝通都必須序列化與反序列化物件。這個邊界代價讓平行化 CPU 密集任務時,開發者往往要仔細切割資料、刻意避免共享狀態,反而增加程式複雜度。SharedArrayBuffer 雖然打開了一道縫,卻只限定型陣列(TypedArray),一般 JS 物件無法直接共用。
PR 描述中直白地說:「你想共用一個物件,就直接共用那個物件(You share an object by sharing the object)」。閉包可以跨執行緒運作,例外可以自然傳播,整個應用程式只需要一個 Map 而不是每個 Worker 各自一份副本。對比 Java 的物件共享模型,這套設計讓 JS 在多核心環境下的思考方式更接近 Java 或 Go,而非傳統 actor 模型。
核心 API 設計
新 API 以最小化表面積為原則,主要入口是 new Thread(fn),傳入一個閉包即可在另一個核心上執行,無需額外設定。同步原語包含 Lock、Condition、ThreadLocal,並將 Atomics.* 擴充套用至普通物件屬性,而不再限於 TypedArray。Thread.restrict(obj) 則可以把特定物件釘在單一執行緒,以明確方式隔離可變狀態,降低資料競爭風險。
對開發者而言最直接的受益場景包括:
- 平行
Array.map(),無需手動切片 - 共享快取(直接用
Map,不用 message passing) - 透過屬性讀取即時監控進度,不需自訂事件協議
- 條件變數實現阻塞式 handoff
引擎架構的代價
要讓多執行緒安全地讀寫同一個堆積,JSC 的物件模型必須大幅改造。PR 引入了 TID 標記的 flat butterfly 結構儲存屬性,並在第一次跨執行緒寫入時轉換為 segmented butterfly 模式,轉換成本約是正常屬性寫入的 7 倍。每個 cell 配置獨立鎖(per-object cell lock)以保護臨界區,JIT 監聽點(watchpoint)也改為 transition-thread-local,讓編譯器仍能在已知物件為執行緒私有時進行最佳化。
效能數據顯示在序列(單執行緒)場景的效能退化維持在 0.45% 最壞情況,符合目標 1% 預算。文件索引基準測試在 16 核心時,JS 執行緒達到 Java 同場景的 0.89 倍,在 16 核心以上超越 Java。全程以 TSAN(Thread Sanitizer)驗證,未出現未抑制的資料競爭,並在所有執行緒數量下維持相同計算結果的 checksum。
現況與展望
Phase 2 目標是移除全域鎖(GIL removal)以實現真正平行,包含每執行緒的 microtask 佇列、event-loop 以及 stop-the-world conductor 協定。Windows 支援與 test262 覆蓋列為尚未開始的項目。CodeRabbit 自動審查識別出超過 20 個問題,涵蓋遺漏的 feature guard 與特定路徑的潛在資料競爭。
這份 PR 的意義不僅在於 Bun,它代表一種對 JS 執行環境根本性的重新設計思路:在不放棄 JS 語意的前提下,讓多核心平行成為一等公民。若此方向最終落地,過去依賴 Worker 池或 Wasm 執行緒才能做到的場景,將有機會以純 JS 更直覺地表達。
原始來源:oven-sh/WebKit PR #249 — shared-memory threads for JavaScriptCore
把整個網站藏進 favicon:用像素 RGB 通道編碼 HTML 的實驗
timwehrle.de · 2026-06-20
德國開發者 Tim Wehrle 在 2026 年 6 月發表一篇實驗性文章,示範如何將 HTML 文件的完整內容編碼進一張 9×9 像素的 PNG favicon 裡。瀏覽器在載入頁面時讀取 favicon 圖片,透過 Canvas API 逆向解碼出 HTML,再將其渲染成完整網站。完整原始碼與互動 demo 已公開於 GitHub timwehrle/favicon。
編碼原理:像素即位元組
技術核心是把 HTML 字串視為位元組流,然後以每個像素的 RGB 三個色彩通道各儲存一個位元組的方式,依序將整份文件「畫」進圖片。編碼流程使用 TextEncoder 將 HTML 轉成 Uint8Array,接著在資料前置一個 4 位元組的標頭,記錄有效負載的總長度,再以三個一組的方式分配給每個像素的 R、G、B 值,最後輸出 PNG。
解碼時,頁面上的 JavaScript bootstrap loader 將 favicon 元素的圖片繪製到一個不可見的 <canvas>,再用 getImageData() 取出像素陣列。讀取前 4 位元組得到原始 HTML 的長度,接著逐像素取出 RGB 值重建 Uint8Array,最後以 TextDecoder 還原為 UTF-8 字串,動態注入 DOM。整個過程完全在瀏覽器端進行,不需要伺服器參與。
實際數據
Wehrle 的示範 payload 尺寸相當小巧,下表呈現關鍵數字:
| 項目 | 數值 |
|---|---|
| HTML 有效負載 | 208 bytes |
| 標頭(長度記錄) | 4 bytes |
| 總計 | 212 bytes |
| 需要像素數 | 71 pixels |
| 最小正方形圖片 | 9×9(81 pixels) |
| 儲存使用率 | 87% |
9×9 像素的圖片比一般 favicon 預設的 16×16 還要小,卻足以容納整份示範 HTML。對比原圖檔大小,這種編碼方式的空間利用率在小型 payload 下相當可觀。
不可避免的限制
Wehrle 在文章中誠實指出這個方案的核心矛盾:favicon 本身並不包含「整個網站」,它只儲存了網站的「內容」。解碼所需的 JavaScript bootstrap 仍然必須存在於原本的 HTML 頁面中,因此無法完全自我包含——瀏覽器沒有辦法直接把一張 favicon 開啟成網站,它需要一個宿主頁面來觸發解碼邏輯。
文章也提及幾種相關的替代手段:SVG favicon 可以直接內嵌 markup;PNG 的 tEXt、zTXt、iTXt metadata chunk 也是藏資料的慣用管道;ICO 格式本身支援多解析度,也有空間可利用。PNG metadata chunk 的方式更「正統」,但 RGB 通道編碼的視覺效果——讓圖片看起來像彩色雜訊——才是這篇文章最讓人印象深刻的示範。
為什麼值得關注
這個實驗的主要意義是教育性質的:它用非常直觀的方式示範了影像格式中「資料即像素、像素即資料」的本質,也展示了 Canvas API 在瀏覽器中作為低階位元組操作工具的能力。對前端工程師而言,getImageData() 與 TextEncoder/TextDecoder 的組合是一個值得納入工具箱的技巧,在需要以圖片通道隱寫少量資料(如浮水印、隱碼術)的場景同樣適用。此實驗也再次說明,瀏覽器所有可請求的資源——包括圖示——都可以成為帶外資料的載體。
可自訂 <select> 的黃金法則:永遠為 option 提供文字內容
WebKit Blog · 2026-06-22
WebKit 團隊在 2026 年 6 月 22 日發表文章,說明即將隨 Safari 27 推出的 Customizable Select 功能有一條核心設計原則:無論怎麼美化 <option> 元素,都必須同時提供文字內容或無障礙文字屬性。這條規則一旦違反,會同時破壞可用性、無障礙功能與舊版瀏覽器的向下相容性三個面向。
Customizable Select 是什麼
長期以來,<select> 是 HTML 中最難客製化的原生元件之一。開發者為了實現圖示選項、自訂箭頭、色票預覽等視覺需求,往往放棄原生 <select> 改用大量 <div> 模擬,代價是失去鍵盤導航、螢幕閱讀器支援與原生表單整合。Customizable Select 讓開發者透過 CSS 屬性 appearance: base-select 解鎖原生 select 的完整視覺控制權,包含自訂箭頭、option 內嵌圖片、色彩配置等,同時保留所有無障礙語意與鍵盤行為。
此功能正在跨瀏覽器推進中,Safari 27 是目前最新的公開里程碑。使用時建議以 @supports (appearance: base-select) 包裹所有客製化樣式,讓不支援的瀏覽器優雅降回系統原生樣式。漸進增強從一開始就是這個規格設計的核心假設,而非事後追加。
黃金法則的具體意義
文章的主旨圍繞一條簡單規則:永遠為 <option> 元素提供文字內容或無障礙文字屬性。這句話看似顯而易見,但當 option 的視覺呈現由純圖示取代文字時,工程師很容易忽略底層的文字節點仍然必要。三個同時失效的場景說明了為何這條規則如此關鍵:
- 可用性:select 關閉狀態(button 部分)只顯示目前選取的 option,若 option 只有圖示沒有文字,使用者無從判斷當前選擇是什麼。
- 無障礙性:螢幕閱讀器、點字顯示器、語音辨識工具依賴無障礙樹(accessibility tree)中的文字節點。即使以 CSS
visually-hidden隱藏文字仍能被輔助技術讀取,但完全省略文字則會讓這些工具無法工作。 - 向下相容:不支援 Customizable Select 的舊版瀏覽器會回退到系統原生 select 樣式,此時 CSS 自訂內容完全消失,option 必須以純文字仍然有意義。
推薦的 HTML 模式
文章給出的建議結構是在 option 內同時放圖片與文字,並讓圖片的 alt 屬性為空(由相鄰文字承擔語意):
<option>
<img src="bird.svg" alt="">
<span>Wildlife</span>
</option>若 option 的視覺由純圖示構成且無法搭配可見文字,則需透過 aria-label 或 aria-labelledby 補充無障礙標籤。CSS visually-hidden class(寬高 1px、clip 截切、overflow hidden)也是常見做法,視覺上隱藏但對輔助技術可見。整個客製化區塊應包在 @supports (appearance: base-select) { } 裡,確保未支援環境不受影響。
對現有前端實踐的影響
Customizable Select 的推出意義在於:它終結了「要無障礙就不能自訂,要自訂就得放棄語意」的兩難困境。但前提是開發者必須從設計稿階段就確保每個 option 有對應的文字標籤。設計系統與 UI 元件庫在實作 option 模板時,若已習慣只放圖示或色票,需要回頭補充 alt / aria-label 或隱藏文字節點,否則在 Customizable Select 環境下反而會因為省略了文字而製造出比舊版 <div> 方案更難察覺的無障礙缺陷。