JavaScript Playground 是一個有界限的編輯器,可在隔離環境中於本機執行簡短的 JavaScript 程式碼片段、擷取主控台輸出與回傳值,並在失控的程式碼凍結頁面其他部分之前停止執行。JavaScript Playground 以刻意的沙箱邊界套用此模式:每個程式碼片段會進入一個全新的、獨立來源 (unique-origin) 的 iframe,在專屬的 Web Worker 中執行,而不會在 UI 執行緒上執行,並會在 1,500 毫秒後終止,無論程式碼是否已完成。網路連線會被 Content Security Policy 封鎖,Worker 環境不開放 DOM、window、localStorage 或 cookie,且僅允許載入內嵌 bootstrap 以及以 Blob 為基礎的 worker。這使得該工具非常適合用來測試純 JavaScript——演算法、陣列、字串、剖析、算術,以及語言實驗——而無需建立完整的 Node.js 或瀏覽器專案。

how to run code in javascript playground
how to run code in javascript playground

JavaScript Playground 實際執行的內容

編輯器接受單一、有界限的 JavaScript 程式碼片段,長度上限為 30,000 字元。在程式碼片段送達 iframe 之前,原始碼會經過 JSON 編碼,並將所有小於字元加以跳脫,因此包含閉合 script 標籤的字串無法突破至 iframe 標記中。每次點擊 Run 都會從頭建立一個全新的隔離環境:一個全新的獨立來源沙箱化 iframe、該 iframe 內部一個新的 Web Worker,以及一個每次執行皆不同的密碼學亂數權杖,所有外傳訊息都必須帶有此權杖。唯有當訊息來源、一個固定的標記,以及當前權杖三者全部相符時,該結果才會被視為真實,這可防止不相關的頁面或擴充功能將偽造的輸出注入結果面板。

執行動作發生於 Worker 而非 UI 執行緒,這就是無限迴圈無法凍結上層頁面的原因。iframe 的 Content Security Policy 預設拒絕所有資源、封鎖網路連線、僅允許內嵌 bootstrap 與 Blob worker,並停用 base URL 與表單動作。iframe 本身允許執行腳本,但拒絕同來源存取、表單提交、導覽、彈出視窗與下載。每次執行都會取代先前的沙箱,因此不會從先前的嘗試中留下任何變數、全域物件、計時器或 worker 控制代碼。

三步驟執行程式碼片段

  1. 輸入不需仰賴 DOM 或 Node.js API 的、有界限 JavaScript 程式碼片段。貼上僅使用語言特性的程式碼——變數、陣列、物件、字串、數學、規則運算式、Promises,以及標準內建項目。任何涉及 document、window、localStorage、fetch 或僅限 Node.js 全域物件的程式碼,都會擲出例外或被靜默封鎖。
  2. 選擇 Run JavaScript 以建立全新的隔離 worker 與沙箱。Playground 會捨棄先前的 iframe,以獨立來源開啟一個新的 iframe、啟動一個專屬的 Web Worker,並將您的程式碼傳送至其中。每次執行皆為獨立,因此輸入錯誤後重新執行時,並不會從先前的執行中帶入任何殘留狀態。
  3. 在修改並重新執行程式碼之前,先檢閱主控台、結果、錯誤或逾時的輸出。檢查主控台面板中的紀錄與錯誤訊息、結果面板中最終運算式的格式化值、錯誤面板中擲出的例外;若 worker 在 1,500 毫秒被終止,則檢查逾時面板。調整程式碼片段後再次執行。

解讀主控台、結果、錯誤與逾時輸出

四個輸出通道幾乎涵蓋了簡短程式碼片段所能產生的一切。主控台會依照執行順序擷取每一次 console.log 與 console.error 呼叫,大多數簡短實驗都會在此回報其發現。當 worker 能將其格式化時,結果欄位會回報最終運算式的值——盡可能使用 JSON,當 JSON 序列化會喪失語意或失敗時,則改以純文字字串作為備案。因此,循環或特殊物件可能會被簡化為可一目了然但無法完整重建的可讀字串。

若程式碼片段擲出例外,該例外會以錯誤的形式呈現,包含其訊息與堆疊。Promise 會被等待:回傳的 promise 會一直被追蹤,直到其 settled,或直到 1,500 毫秒的 wall-clock 保護機制觸發,以先發生者為準。當保護機制觸發時,worker 會被終止,上層頁面不受影響,Playground 會回報逾時而非結果。由於逾時屬於安全防護機制,而非效能基準,實際的完成時間取決於瀏覽器的排程,以及您的程式碼片段排定了多少非同步工作。

沙箱刻意封鎖的項目

Worker 內可使用遭封鎖或不可用
變數、常值、運算式DOM 存取 (document、elements、events)
陣列、字串、物件、Map、Setwindow、localStorage、sessionStorage
Math、Number、BigInt、JSON 剖析Cookie 與頁面工作階段狀態
規則運算式fetch、XHR、WebSocket、網路請求
Promises、async/await、generators表單提交、導覽、彈出視窗、下載
Date、Intl、TypedArrays僅限 Node.js 的 API 與 npm 套件
使用者自訂函式與類別TypeScript 編譯或轉譯
主控台輸出擷取各次執行之間的持續性儲存

此封鎖清單是由 iframe 的沙箱旗標、其 Content Security Policy,以及 Worker 環境中缺少這些全域物件所強制執行的——並非依賴頁面內部的誠實原則。若您需要上述任何被封鎖的功能,則必須使用其他工具:本機 Node.js 環境、瀏覽器 DevTools 主控台,或具備版本控制、且會在正式環境中實際執行程式碼的執行階段的專案。

適合 Playground 的場景

該沙箱專為執行純 JavaScript 的簡短、確定性實驗而打造。這包括陣列與字串轉換、小型剖析常式、規則運算式草稿、數學與 BigInt 實驗、JSON 序列化檢查,以及您希望在晉升至更大專案前先行驗證的微型演算法。Promise 最多可測試至 1,500 毫秒的截止時間,這對於幾乎所有不依賴實際網路 I/O 的實用程式碼片段皆已足夠。

由於每次執行皆為全新環境,您可以快速迭代,而無需在每次嘗試之間清理全域物件、計時器或殘留的事件監聽器。若程式碼片段擲出例外,請修正程式碼後重新執行;先前的 worker 早已被取代。若程式碼片段靜默地什麼都不回傳,請加入中間值的 console.log,並在下一次執行時檢查主控台面板。

貼上之前值得了解的限制

編輯器將程式碼片段上限設為 30,000 字元,這對幾乎所有自給自足的實驗而言已相當充裕,但小於許多真實的原始程式檔案。該工具不儲存任何專案,亦不提供匯入、套件、Node.js API、TypeScript 編譯、除錯中斷點或持續性檔案。每次執行皆為單一、隔離的執行:沒有可儲存的狀態、沒有先前執行的紀錄,也無法在同一工作階段中串接多個程式碼片段。

1,500 毫秒的逾時是用來抵禦失控程式碼的 wall-clock 防護機制,而非衡量程式碼片段執行速度的基準。瀏覽器排程會有所差異,因此即使程式碼片段行為良好,非同步工作仍可能在完成前就被終止。對於需要持續性儲存、匯入、除錯或更豐富執行階段的程式碼,請設定一個具備版本控制的本機專案,並加入測試、linting、相依性檢視,以及實際執行該程式碼的執行階段。

該沙箱是一道防禦邊界,而非用來執行未知或不受信任程式碼的邀請。請於執行前檢閱程式碼片段,切勿將密碼、API 金鑰、工作階段權杖、私密客戶資料或專屬原始碼貼入任何線上編輯器——本工具亦不例外。隔離機制保護的是您正在閱讀的頁面;它並不會保護您自願交給遠端服務的機密資料。

若想了解底層機制的背景——Web Workers、iframe 的 sandbox 屬性,以及 Content Security Policy——MDN Web Workers API 參考資料MDN iframe sandbox 說明文件皆有詳細描述。

若想深入了解,請參閱 在 VS Code 中壓縮 JSON 而不破壞數字

若想深入了解,請參閱 產生 ANSI 色彩碼時如何避免錯誤