基於瀏覽器的 JavaScript 遊樂場可以在隔離的 Web Worker 中執行受限制的程式碼片段,取代需要 API 的工具,無需 API 金鑰、無需註冊,也無需網路存取。JavaScript 遊樂場在獨特來源且封鎖網路的沙箱中,以時間限制的 worker 執行簡短的 JavaScript 片段,所有輸出都會在同一個分頁中擷取。程式碼永遠不會離開你的電腦,每次執行時沙箱都會重新建立,而 1,500 毫秒的牆鐘時間限制會強制結束任何拒絕退出的迴圈。主控台訊息、傳回值和擲回的錯誤都會顯示在輸出面板中,因此你可以不離開頁面就檢視結果。這讓它成為依賴伺服器端執行 API、帳號或身分驗證權杖之遊樂場的實用替代方案。它的設計目的是用於語言實驗、演算法草稿、正則表達式檢查以及快速的資料結構檢查,而不是完整應用程式或任何涉及 DOM、網路或 Node.js 內建模組的東西。

基於 API 的 JavaScript 遊樂場的不足之處
大多數託管的 JavaScript 遊樂場依賴後端執行服務。你將程式碼貼到瀏覽器編輯器中,編輯器透過 HTTPS 將原始碼傳送到遠端端點,該端點在伺服器上啟動容器或無伺服器函式,結果透過 websocket 或輪詢通道串流回來。這種架構可解鎖完整的 Node.js 存取和長時間執行程序,但它也引入了一堆使用者必須先滿足才能執行第一個片段的需求。
這種摩擦通常出現在同樣的五個地方:
- API 金鑰或帳號。伺服器端執行需要計費、速率限制和身分驗證權杖,因此遊樂場會限制匿名使用。
- 外傳的網路呼叫。你的原始文字會離開瀏覽器,這使得工作流程不適合包含專屬邏輯、客戶資料或未公開功能程式碼的片段。
- 延遲。從編輯器到容器再來回的往返時間會累積,特別是對於答案應該幾乎立即出現的簡短片段。
- 服務可用性。遊樂場的可達性取決於其後端,中斷、配額耗盡或 API 版本漂移都可能破壞你以為在本機的工作流程。
- 狀態存放在別人的資料庫中。許多託管的遊樂場預設會保存片段、fork 和修訂,這會使合規審查變得複雜,並增加資料保留的工作量。
瀏覽器本機的遊樂場消除了上述清單中的每一項。腳本在你輸入它的同一個分頁中執行,結果出現在編輯器旁邊,完全不涉及瀏覽器以外的基礎架構。
瀏覽器本機沙箱如何取代 API
JavaScript 遊樂場實作了基於 API 的服務通常在其伺服器上強制執行的隔離合約,但完全使用瀏覽器原語來達成。每次執行都從一個全新的 iframe 開始,該 iframe 使用 sandbox="allow-scripts" 屬性和獨特的不透明來源建立。iframe 的內容安全策略預設拒絕所有資源,透過 connect-src 'none' 封鎖所有網路連線,並停用基礎 URL 和表單動作。iframe 允許執行腳本和啟動以 Blob 支援的 Web Worker,但它無法導覽父頁面、開啟彈出視窗、提交表單,或讀取父頁面的 cookie 和儲存空間。sandbox 屬性本身記載於 MDN iframe sandbox 參考資料中。
你的原始文字在插入 iframe 之前會先進行 JSON 編碼,並跳脫所有小於字元,使得包含結束 </script> 標籤的字串常值無法從其容器中逃逸。一旦引導程式執行,你的程式碼就會載入 Web Worker,這才是實際執行的地方。worker 沒有 DOM、document、window、localStorage、cookie,也沒有 session storage。它無法呼叫 fetch,因為 CSP 禁止網路連線,而且也沒有套件執行環境可供匯入。
輸出透過 postMessage 回傳。在接受任何訊息之前,父頁面會檢查三件事:訊息來自預期的 iframe 視窗、來源標記符合啟動它的執行階段、且每次執行的權杖符合為該執行階段產生的加密值。如果這些檢查中有任何一項失敗,該訊息就會被捨棄。獨特來源、JSON 插入的原始碼和三重檢查的訊息傳遞這三者的組合,正是讓沙箱無需伺服器就能安全使用的關鍵。
在 JavaScript 遊樂場中執行片段
- 在瀏覽器中開啟 JavaScript 遊樂場。編輯器最多接受 30,000 個字元,啟動時為空白或包含一個小型的起始片段。
- 輸入不需要 DOM、網路或 Node.js API 的受限制 JavaScript 片段。僅使用陣列、字串、物件、算術、正則表達式和語言實驗。
- 選擇執行 JavaScript。將建立一個全新的獨特來源 iframe 和 Web Worker,並為此次執行產生一個新的加密權杖。
- 檢閱主控台、結果、錯誤或逾時面板。console.log 和 console.error 輸出會以個別項目顯示,最終運算式在可以格式化時會被回報為結果。
- 編輯原始碼並再次執行。每次執行都會取代先前的沙箱,因此先前執行的剩餘狀態無法洩漏到下一次執行中。
沙箱允許和拒絕的內容
| 功能 | 沙箱中的狀態 |
|---|---|
| 純 JavaScript 運算 | 允許 |
| console.log 和 console.error | 擷取並顯示在輸出面板中 |
| 最終運算式作為傳回值 | 在可能的情況下以格式化結果回報 |
| Promise 和 async / await | 在 Promise 解決或逾時結束 worker 之前允許 |
| DOM 存取 (document, window) | 拒絕 — worker 沒有 DOM 繫結 |
| fetch、XMLHttpRequest 或任何網路呼叫 | 拒絕 — CSP 封鎖所有網路連線 |
| 套件匯入或 Node.js 內建模組 | 拒絕 — 未提供模組載入器 |
| localStorage、cookie、session storage | 拒絕 — worker 沒有儲存 API |
| 持續性專案或檔案儲存 | 拒絕 — 每次執行都從全新的沙箱開始 |
| 長時間執行的迴圈 | 在 1,500 毫秒時終止 |
拒絕清單就是安全性模型。將沙箱視為防禦邊界,而不是執行你尚未審閱之片段的綠燈。任何線上編輯器,包括這個在內,都不是處理密碼、API 金鑰、工作階段權杖、客戶資料或專屬原始碼的適當場所。
適合 1.5 秒時間窗的用途
1,500 毫秒的上限對於短小、確定性的片段綽綽有餘,但對於迴圈處理大型輸入的任何內容來說則很緊迫。遠在預算內就能完成的任務包括排序小型陣列、對映和篩選練習、使用 split 和 match 進行字串剖析、JSON 結構探索、算術健全性檢查,以及快速的正則表達式實驗。典型的用途是貼上一個棘手的正則表達式,確認特定輸入是否符合預期的擷取群組,然後再將該模式複製到專案中 — 這類檢查涵蓋於 如何在 JavaScript 中檢查正則表達式模式中。
通常不適合的任務包括任何處理數百萬列的內容、任何需要串流或分塊 I/O 的內容,以及任何依賴資料庫或遠端 API 的內容。如果片段需要 fetch 或匯入,沙箱將拒絕網路呼叫,無論時鐘上還剩下多少時間。
並列比較遊樂場方法
| 屬性 | 瀏覽器本機沙箱 (JavaScript 遊樂場) | 託管的基於 API 遊樂場 |
|---|---|---|
| 需要 API 金鑰或註冊 | 否 | 通常是 |
| 原始碼離開瀏覽器 | 否 | 是 |
| 使用者程式碼的網路存取 | 由 CSP 封鎖 | 可用 |
| DOM 和 window API | 不可用 | 在瀏覽器 iframe 中可用 |
| Node.js 內建模組和套件 | 未提供 | 通常可用 |
| 執行位置 | 同一分頁中的 Web Worker | 遠端容器或無伺服器函式 |
| 預設執行上限 | 1,500 毫秒牆鐘時間 | 依方案而異 |
| 持續性專案 | 無 | 通常是 |
| 貼上前的程式碼審閱 | 必要 — 沙箱是防禦邊界,不是惡意程式碼的沙箱 | 同樣的責任適用 |
這兩欄解決的是不同的問題。如果你想評估語言行為、草擬演算法,或針對小型測試資料檢查正則表達式,瀏覽器本機沙箱消除了所有帳號和配額障礙。如果你需要多檔案專案、真實的 DOM 渲染,或伺服器端執行環境,託管的遊樂場才是正確的工具,你應該選擇一家你已閱讀過其安全性模型的供應商。
本機專案何時成為更好的工具
逾時是牆鐘時間防護,而不是效能基準。瀏覽器排程在不同的分頁和裝置之間有所不同,因此非同步工作即使在再過幾毫秒就會完成的情況下,仍可能會在邏輯上完成之前就被終止。對於生產程式碼,你仍然應該使用具有版本控制、本機測試、程式碼檢查、相依項目審閱以及實際執行該程式碼之執行環境的本機專案。遊樂場是用來回答單一問題的草稿區;儲存庫則是用來保存答案的地方。
執行程式碼片段之前先審閱它們,將沙箱視為防禦邊界,並將機密資料排除在編輯器之外。這三個習慣正是讓瀏覽器本機 JavaScript 遊樂場成為其設計目的之小型實驗的安全預設選擇的原因。