非沙箱擴充功能
非沙箱擴充功能作為主頁面中的普通 <script> 標籤執行,而不是在沙箱中。這讓它們可以存取 Bilup 的內部,以及一組相應的責任。
擴充功能何時以非沙箱方式執行
Bilup 決定如何載入每個擴充功能:
-
從檔案或貼上的程式碼載入:自訂擴充功能對話方塊有一個"不進入沙箱執行擴充功能"核取方塊。由您選擇。
-
從 URL 載入:只有當 URL 恰好以下面一個受信任字首開頭時,它才自動以非沙箱方式執行:
https://extensions.bilup.org/https://extensions.turbowarp.org/http://localhost:8000/
任何其他 URL 都以沙箱方式載入,除非使用者手動選擇信任它。無法強制任意 URL 以非沙箱方式載入,這是故意的,為了保護使用者免受惡意擴充功能的侵害。
由於您不控制那兩個畫廊域名,開發期間您從 http://localhost:8000/ 提供擴充功能。將您的本地伺服器指向 8000 埠。它必須恰好是 8000 埠上的 localhost;127.0.0.1 和 0.0.0.0 不會被視為受信任。
模板
語法與沙箱擴充功能幾乎相同,包裹在立即呼叫函式表示式(IIFE)中並使用嚴格模式:
(function(Scratch) {
'use strict';
class MyExtension {
getInfo() {
return { /* ... */ };
}
}
Scratch.extensions.register(new MyExtension());
})(Scratch);
IIFE 防止非沙箱擴充功能相互干擾。因為它們共享一個頁面,兩個都宣告全域 vm 或 helper 的擴充功能會衝突。將一切包裹在帶 'use strict' 的函式中可以讓您的變數保持私有,並給 每個擴充功能自己的 Scratch 副本。
您的擴充功能定義的每個變數、函式和類都必須位於 IIFE 內部。這個模板也是向後相容的:只要不使用任何僅非沙箱的功能,同樣的程式碼在沙箱載入時仍然有效。
這裡有一個完整的非沙箱 hello world(下載):
(function(Scratch) {
'use strict';
if (!Scratch.extensions.unsandboxed) {
throw new Error('This Hello World example must run unsandboxed');
}
class HelloWorld {
getInfo() {
return {
id: 'helloworldunsandboxed',
name: 'Unsandboxed Hello World',
blocks: [
{ opcode: 'hello', blockType: Scratch.BlockType.REPORTER, text: 'Hello!' }
]
};
}
hello() {
return 'World!';
}
}
Scratch.extensions.register(new HelloWorld());
})(Scratch);
在 http://localhost:8000/hello-world-unsandboxed.js 提供它並載入那個確切 URL。把它的積木放進一個將它加入列表的 重複執行 (30) 中;它會立即執行,而沙箱版本至少要花一秒。
新責任
非沙箱程式碼與使用者的專案在同一頁面上執行,因此一個錯誤可能造成真正的損害:
- 積木絕不能丟擲異常。 丟擲的錯誤可能破壞執行該積木的指令碼。
- 報告和布林積木必須返回有效值(字串、數字或布林值)。返回
undefined可能以令人困惑的方式破壞指令碼。 - 積木絕不能陷入無限迴圈。 掛起的沙箱擴充功能通常只是停滯自身;非沙箱的會凍結整個頁面,這可能 導致資料丟失。
如果您的擴充功能確實需要非沙箱模式,請響亮且儘早地失敗:
if (!Scratch.extensions.unsandboxed) {
throw new Error('My Extension must run unsandboxed');
}