非沙箱扩展
非沙箱扩展作为主页面中的普通 <script> 标签运行,而不是在沙箱中。这让它们可以访问 RemixWarp 的内部,以及一组相应的责任。
扩展何时以非沙箱方式运行
RemixWarp 决定如何加载每个扩展:
-
从文件或粘贴的代码加载:自定义扩展对话框有一个"不进入沙箱运行扩展"复选框。由您选择。
-
从 URL 加载:只有当 URL 恰好以下面一个受信任前缀开头时,它才自动以非沙箱方式运行:
https://extensions.remixwarp.pages.dev/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');
}
访问 RemixWarp 内部
头条功能是 Scratch.vm,实际的 VM 对象:
const vm = Scratch.vm;
从那里可以访问很多东西。记住每个声明都放在 IIFE 内部:
// 好
(function(Scratch) {
const vm = Scratch.vm;
// ...
}(Scratch));
// 坏:泄漏一个全局
const vm = Scratch.vm;
(function(Scratch) { /* ... */ }(Scratch));
您的开发者控制台是最好的探索方式:扩展加载后,您可以在那里检查 Scratch 和 vm。scratch-vm 源码是存在什么的参考。
这里有一个通过 VM 切换涡轮模式的扩展(下载):
(function(Scratch) {
'use strict';
if (!Scratch.extensions.unsandboxed) {
throw new Error('This Turbo Mode example must run unsandboxed');
}
const vm = Scratch.vm;
class TurboMode {
getInfo() {
return {
id: 'turbomodeunsandboxed',
name: 'Turbo Mode',
blocks: [
{
opcode: 'set',
blockType: Scratch.BlockType.COMMAND,
text: 'set turbo mode to [ENABLED]',
arguments: {
ENABLED: { type: Scratch.ArgumentType.STRING, menu: 'ENABLED_MENU' }
}
}
],
menus: {
ENABLED_MENU: { acceptReporters: true, items: ['on', 'off'] }
}
};
}
set(args) {
vm.setTurboMode(args.ENABLED === 'on');
}
}
Scratch.extensions.register(new TurboMode());
})(Scratch);