移除顶级await以适配<chrome89版本
This commit is contained in:
parent
11b971c0c2
commit
0ab098cf42
|
@ -10,7 +10,7 @@ import * as config from "../util/config.js";
|
||||||
import { promiseErrorHandlerMap } from "../util/browser.js";
|
import { promiseErrorHandlerMap } from "../util/browser.js";
|
||||||
import { importCardPack, importCharacterPack, importExtension, importMode } from "./import.js";
|
import { importCardPack, importCharacterPack, importExtension, importMode } from "./import.js";
|
||||||
import { onload } from "./onload.js";
|
import { onload } from "./onload.js";
|
||||||
import security from "../util/security.js";
|
import { initializeSandboxRealms } from "../util/initRealms.js";
|
||||||
|
|
||||||
// 判断是否从file协议切换到http/s协议
|
// 判断是否从file协议切换到http/s协议
|
||||||
export function canUseHttpProtocol() {
|
export function canUseHttpProtocol() {
|
||||||
|
@ -125,7 +125,12 @@ export async function boot() {
|
||||||
// 加载polyfill内容
|
// 加载polyfill内容
|
||||||
await import("./polyfill.js");
|
await import("./polyfill.js");
|
||||||
|
|
||||||
|
// 初始化沙盒的Realms
|
||||||
|
await initializeSandboxRealms();
|
||||||
|
|
||||||
// 初始化security
|
// 初始化security
|
||||||
|
const securityModule = await import("../util/security.js");
|
||||||
|
const security = securityModule.default;
|
||||||
security.initSecurity({
|
security.initSecurity({
|
||||||
lib, game, ui, get, ai, _status, gnc,
|
lib, game, ui, get, ai, _status, gnc,
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,7 +12,6 @@ import { GameEventPromise } from "../element/gameEventPromise.js";
|
||||||
import { rootURL } from "../../../noname.js";
|
import { rootURL } from "../../../noname.js";
|
||||||
|
|
||||||
import security from "../../util/security.js";
|
import security from "../../util/security.js";
|
||||||
import { Domain, Marshal, Sandbox } from "../../util/sandbox.js";
|
|
||||||
|
|
||||||
export class LibInit {
|
export class LibInit {
|
||||||
/**
|
/**
|
||||||
|
@ -596,32 +595,15 @@ export class LibInit {
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
parsex(item, scope) {
|
parsex(item, scope) {
|
||||||
let ModFunction = Function;
|
|
||||||
let ModGeneratorFunction = GeneratorFunction;
|
|
||||||
// let ModAsyncFunction = AsyncFunction;
|
|
||||||
// let ModAsyncGeneratorFunction = AsyncGeneratorFunction;
|
|
||||||
|
|
||||||
// 虽然现在 parsex 被控制到了沙盒,
|
// 虽然现在 parsex 被控制到了沙盒,
|
||||||
// 但是因为默认沙盒还是可以额外操作东西,
|
// 但是因为默认沙盒还是可以额外操作东西,
|
||||||
// 故而对不同的运行域做了区分
|
// 故而对不同的运行域做了区分
|
||||||
if (security.SANDBOX_ENABLED) {
|
let [
|
||||||
const domain = Marshal.getMarshalledDomain(item) || Domain.caller;
|
|
||||||
|
|
||||||
// 非顶级域调用情况下我们替换掉Function类型
|
|
||||||
if (domain && domain !== Domain.topDomain) {
|
|
||||||
const sandbox = Sandbox.from(domain);
|
|
||||||
|
|
||||||
if (!sandbox)
|
|
||||||
throw "意外的运行域: 运行域没有绑定沙盒";
|
|
||||||
|
|
||||||
[
|
|
||||||
ModFunction,
|
ModFunction,
|
||||||
ModGeneratorFunction,
|
ModGeneratorFunction,
|
||||||
// ModAsyncFunction,
|
// ModAsyncFunction,
|
||||||
// ModAsyncGeneratorFunction,
|
// ModAsyncGeneratorFunction,
|
||||||
] = security.getIsolateds(sandbox);
|
] = security.getIsolatedsFrom(item);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//by 诗笺、Tipx-L
|
//by 诗笺、Tipx-L
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,7 +21,6 @@ import {
|
||||||
getTreesFromGithub,
|
getTreesFromGithub,
|
||||||
} from "../../../../library/update.js";
|
} from "../../../../library/update.js";
|
||||||
import security from "../../../../util/security.js";
|
import security from "../../../../util/security.js";
|
||||||
import { AccessAction, Marshal, Monitor } from "../../../../util/sandbox.js";
|
|
||||||
|
|
||||||
export const otherMenu = function (/** @type { boolean | undefined } */ connectMenu) {
|
export const otherMenu = function (/** @type { boolean | undefined } */ connectMenu) {
|
||||||
if (connectMenu) return;
|
if (connectMenu) return;
|
||||||
|
@ -1215,6 +1214,7 @@ export const otherMenu = function (/** @type { boolean | undefined } */ connectM
|
||||||
cheat: lib.cheat,
|
cheat: lib.cheat,
|
||||||
});
|
});
|
||||||
if (security.isSandboxRequired()) {
|
if (security.isSandboxRequired()) {
|
||||||
|
const { Monitor, AccessAction } = security.importSandbox();
|
||||||
new Monitor()
|
new Monitor()
|
||||||
.action(AccessAction.DEFINE)
|
.action(AccessAction.DEFINE)
|
||||||
.action(AccessAction.WRITE)
|
.action(AccessAction.WRITE)
|
||||||
|
|
|
@ -0,0 +1,121 @@
|
||||||
|
// 为了兼容无法使用顶级await的版本
|
||||||
|
const iframe = document.createElement("iframe");
|
||||||
|
|
||||||
|
// 执行上下文传递函数,请勿动喵
|
||||||
|
// 用于传递顶级execute context
|
||||||
|
|
||||||
|
/** @type {(target: Function, thiz: Object, args: Array) => any} */
|
||||||
|
// @ts-ignore
|
||||||
|
const ContextInvoker1 = (function (apply, target, thiz, args) {
|
||||||
|
return apply(target, thiz, args);
|
||||||
|
}).bind(null, Reflect.apply);
|
||||||
|
|
||||||
|
/** @type {(target: Function, args: Array, newTarget: Function) => any} */
|
||||||
|
// @ts-ignore
|
||||||
|
const ContextInvoker2 = (function (construct, target, args, newTarget) {
|
||||||
|
return construct(target, args, newTarget);
|
||||||
|
}).bind(null, Reflect.construct);
|
||||||
|
|
||||||
|
/** @type {(closure: Object, target: Function) => ((...args: any[]) => any)} */
|
||||||
|
// @ts-ignore
|
||||||
|
const ContextInvokerCreator = (function (apply, closure, target) {
|
||||||
|
return function (...args) {
|
||||||
|
return apply(target, closure,
|
||||||
|
// @ts-ignore
|
||||||
|
[this === window ? null : this, args, new.target]);
|
||||||
|
};
|
||||||
|
}).bind(null, Reflect.apply);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} path
|
||||||
|
* @param {string} name
|
||||||
|
*/
|
||||||
|
function replaceName(path, name) {
|
||||||
|
const index = path.lastIndexOf("/");
|
||||||
|
return path.slice(0, index + 1) + name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TARGET_URL = replaceName(import.meta.url, "sandbox.js");
|
||||||
|
const SANDBOX_EXPORT = {};
|
||||||
|
|
||||||
|
async function initializeSandboxRealms() {
|
||||||
|
const document = window.document;
|
||||||
|
const createElement = document.createElement.bind(document);
|
||||||
|
const appendChild = document.body.appendChild.bind(document.body);
|
||||||
|
|
||||||
|
// 通过构造 iframe 来创建新的变量域
|
||||||
|
// 我们需要确保顶级运行域的原型链不暴露
|
||||||
|
// 为此我们从新的变量域重新载入当前脚本
|
||||||
|
// 然后就可以直接冻结当前变量域的原型链
|
||||||
|
const iframe = createElement("iframe");
|
||||||
|
iframe.style.display = "none";
|
||||||
|
appendChild(iframe);
|
||||||
|
|
||||||
|
if (!iframe.contentWindow)
|
||||||
|
throw new ReferenceError("无法载入运行域");
|
||||||
|
|
||||||
|
// 定义 createRealms 函数
|
||||||
|
Reflect.defineProperty(iframe.contentWindow, "createRealms", {
|
||||||
|
value() {
|
||||||
|
// 通过构造 iframe 来创建新的变量域
|
||||||
|
const iframe = createElement("iframe");
|
||||||
|
iframe.style.display = "none";
|
||||||
|
appendChild(iframe);
|
||||||
|
|
||||||
|
const window = iframe.contentWindow;
|
||||||
|
if (!window)
|
||||||
|
throw new ReferenceError("顶级域已经被卸载");
|
||||||
|
|
||||||
|
iframe.remove();
|
||||||
|
return window;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 传递顶级变量域、上下文执行器
|
||||||
|
// @ts-ignore
|
||||||
|
iframe.contentWindow.replacedGlobal = window;
|
||||||
|
// @ts-ignore
|
||||||
|
iframe.contentWindow.replacedCI1 = ContextInvoker1;
|
||||||
|
// @ts-ignore
|
||||||
|
iframe.contentWindow.replacedCI2 = ContextInvoker2;
|
||||||
|
// @ts-ignore
|
||||||
|
iframe.contentWindow.replacedCIC = ContextInvokerCreator;
|
||||||
|
|
||||||
|
// 重新以新的变量域载入当前脚本
|
||||||
|
const script = iframe.contentWindow.document.createElement("script");
|
||||||
|
script.src = TARGET_URL;
|
||||||
|
script.type = "module";
|
||||||
|
|
||||||
|
// 无法同步载入
|
||||||
|
// script.async = false;
|
||||||
|
// script.defer = false;
|
||||||
|
|
||||||
|
const promise = new Promise((resolve, reject) => {
|
||||||
|
script.onload = resolve;
|
||||||
|
script.onerror = reject;
|
||||||
|
});
|
||||||
|
iframe.contentWindow.document.head.appendChild(script);
|
||||||
|
await promise; // Top Await Required Chrome 89
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
if (!iframe.contentWindow.SANDBOX_EXPORT)
|
||||||
|
throw new ReferenceError("无法同步载入运行域");
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
delete iframe.contentWindow.replacedGlobal;
|
||||||
|
// @ts-ignore
|
||||||
|
delete iframe.contentWindow.replacedCI1;
|
||||||
|
// @ts-ignore
|
||||||
|
delete iframe.contentWindow.replacedCI2;
|
||||||
|
// @ts-ignore
|
||||||
|
delete iframe.contentWindow.replacedCIC;
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
Object.assign(SANDBOX_EXPORT, iframe.contentWindow.SANDBOX_EXPORT);
|
||||||
|
iframe.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
initializeSandboxRealms,
|
||||||
|
SANDBOX_EXPORT,
|
||||||
|
};
|
|
@ -1,4 +1,9 @@
|
||||||
const FILE_URL = import.meta.url;
|
import { SANDBOX_EXPORT } from "./initRealms.js";
|
||||||
|
|
||||||
|
// 很重要的事情!
|
||||||
|
// 请不要在在其他文件中import sandbox.js!
|
||||||
|
// 如果需要沙盒相关的类请用security.importSandbox()导入!!!
|
||||||
|
// 什么时候支持顶级await(Chrome 89)就可以改回去了,现在好麻烦哦
|
||||||
|
|
||||||
/** @typedef {any} Window */
|
/** @typedef {any} Window */
|
||||||
|
|
||||||
|
@ -1030,28 +1035,15 @@ class NativeWrapper {
|
||||||
|
|
||||||
/** @type {(target: Function, thiz: Object, args: Array) => any} */
|
/** @type {(target: Function, thiz: Object, args: Array) => any} */
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const ContextInvoker1 = window.replacedCI1
|
const ContextInvoker1 = window.replacedCI1;
|
||||||
|| (function (apply, target, thiz, args) {
|
|
||||||
return apply(target, thiz, args);
|
|
||||||
}).bind(null, Reflect.apply);
|
|
||||||
|
|
||||||
/** @type {(target: Function, args: Array, newTarget: Function) => any} */
|
/** @type {(target: Function, args: Array, newTarget: Function) => any} */
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const ContextInvoker2 = window.replacedCI2
|
const ContextInvoker2 = window.replacedCI2;
|
||||||
|| (function (construct, target, args, newTarget) {
|
|
||||||
return construct(target, args, newTarget);
|
|
||||||
}).bind(null, Reflect.construct);
|
|
||||||
|
|
||||||
/** @type {(closure: Object, target: Function) => ((...args: any[]) => any)} */
|
/** @type {(closure: Object, target: Function) => ((...args: any[]) => any)} */
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const ContextInvokerCreator = window.replacedCIC
|
const ContextInvokerCreator = window.replacedCIC;
|
||||||
|| (function (apply, closure, target) {
|
|
||||||
return function (...args) {
|
|
||||||
return apply(target, closure,
|
|
||||||
// @ts-ignore
|
|
||||||
[this === window ? null : this, args, new.target]);
|
|
||||||
};
|
|
||||||
}).bind(null, Reflect.apply);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ```plain
|
* ```plain
|
||||||
|
@ -3521,89 +3513,9 @@ function sealObject(obj, freeze = Object.freeze) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const SANDBOX_EXPORT = {
|
|
||||||
AccessAction,
|
|
||||||
Rule,
|
|
||||||
Monitor,
|
|
||||||
Marshal,
|
|
||||||
Domain,
|
|
||||||
Sandbox,
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: 其他扩展的全局变量
|
|
||||||
|
|
||||||
if (SANDBOX_ENABLED) {
|
if (SANDBOX_ENABLED) {
|
||||||
// 确保顶级运行域的原型链不暴露
|
// 确保顶级运行域的原型链不暴露
|
||||||
if (window.top === window) {
|
if (window.top === window) {
|
||||||
// 如果当前是顶级运行域
|
|
||||||
const document = window.document;
|
|
||||||
const createElement = document.createElement.bind(document);
|
|
||||||
const appendChild = document.body.appendChild.bind(document.body);
|
|
||||||
|
|
||||||
// 通过构造 iframe 来创建新的变量域
|
|
||||||
// 我们需要确保顶级运行域的原型链不暴露
|
|
||||||
// 为此我们从新的变量域重新载入当前脚本
|
|
||||||
// 然后就可以直接冻结当前变量域的原型链
|
|
||||||
const iframe = createElement("iframe");
|
|
||||||
iframe.style.display = "none";
|
|
||||||
appendChild(iframe);
|
|
||||||
|
|
||||||
if (!iframe.contentWindow)
|
|
||||||
throw new ReferenceError("无法载入运行域");
|
|
||||||
|
|
||||||
// 定义 createRealms 函数
|
|
||||||
Reflect.defineProperty(iframe.contentWindow, "createRealms", {
|
|
||||||
value() {
|
|
||||||
// 通过构造 iframe 来创建新的变量域
|
|
||||||
const iframe = createElement("iframe");
|
|
||||||
iframe.style.display = "none";
|
|
||||||
appendChild(iframe);
|
|
||||||
|
|
||||||
const window = iframe.contentWindow;
|
|
||||||
if (!window)
|
|
||||||
throw new ReferenceError("顶级域已经被卸载");
|
|
||||||
|
|
||||||
iframe.remove();
|
|
||||||
return window;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// 传递顶级变量域、上下文执行器
|
|
||||||
// @ts-ignore
|
|
||||||
iframe.contentWindow.replacedGlobal = window;
|
|
||||||
// @ts-ignore
|
|
||||||
iframe.contentWindow.replacedCI1 = ContextInvoker1;
|
|
||||||
// @ts-ignore
|
|
||||||
iframe.contentWindow.replacedCI2 = ContextInvoker2;
|
|
||||||
// @ts-ignore
|
|
||||||
iframe.contentWindow.replacedCIC = ContextInvokerCreator;
|
|
||||||
|
|
||||||
// 重新以新的变量域载入当前脚本
|
|
||||||
const script = iframe.contentWindow.document.createElement("script");
|
|
||||||
script.src = FILE_URL;
|
|
||||||
script.type = "module";
|
|
||||||
|
|
||||||
const promise = new Promise((resolve, reject) => {
|
|
||||||
script.onload = resolve;
|
|
||||||
script.onerror = reject;
|
|
||||||
});
|
|
||||||
iframe.contentWindow.document.head.appendChild(script);
|
|
||||||
await promise;
|
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
delete iframe.contentWindow.replacedGlobal;
|
|
||||||
// @ts-ignore
|
|
||||||
delete iframe.contentWindow.replacedCI1;
|
|
||||||
// @ts-ignore
|
|
||||||
delete iframe.contentWindow.replacedCI2;
|
|
||||||
// @ts-ignore
|
|
||||||
delete iframe.contentWindow.replacedCIC;
|
|
||||||
|
|
||||||
// 从新的变量域暴露的对象获取导出
|
|
||||||
// @ts-ignore
|
|
||||||
Object.assign(SANDBOX_EXPORT, iframe.contentWindow.SANDBOX_EXPORT);
|
|
||||||
iframe.remove(); // 释放 iframe 与相关的 browser context
|
|
||||||
|
|
||||||
({
|
({
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
AccessAction,
|
AccessAction,
|
||||||
|
@ -3658,8 +3570,14 @@ if (SANDBOX_ENABLED) {
|
||||||
|
|
||||||
// 向顶级运行域暴露导出
|
// 向顶级运行域暴露导出
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
window.SANDBOX_EXPORT =
|
window.SANDBOX_EXPORT = {
|
||||||
Object.assign({}, SANDBOX_EXPORT);
|
AccessAction,
|
||||||
|
Rule,
|
||||||
|
Monitor,
|
||||||
|
Marshal,
|
||||||
|
Domain,
|
||||||
|
Sandbox,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import { Sandbox, Domain, Marshal, Monitor, AccessAction, Rule, SANDBOX_ENABLED } from "./sandbox.js";
|
|
||||||
|
|
||||||
// 是否强制所有模式下使用沙盒
|
// 是否强制所有模式下使用沙盒
|
||||||
const SANDBOX_FORCED = true;
|
const SANDBOX_FORCED = true;
|
||||||
// 是否启用自动测试
|
// 是否启用自动测试
|
||||||
|
@ -12,11 +10,37 @@ const TRUSTED_IPS = Object.freeze([
|
||||||
"47.99.105.222",
|
"47.99.105.222",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
/** @type {boolean} */
|
||||||
|
let SANDBOX_ENABLED = true;
|
||||||
|
/** @type {typeof import("./sandbox.js").AccessAction} */
|
||||||
|
let AccessAction;
|
||||||
|
/** @type {typeof import("./sandbox.js").Domain} */
|
||||||
|
let Domain;
|
||||||
|
/** @type {typeof import("./sandbox.js").Marshal} */
|
||||||
|
let Marshal;
|
||||||
|
/** @type {typeof import("./sandbox.js").Monitor} */
|
||||||
|
let Monitor;
|
||||||
|
/** @type {typeof import("./sandbox.js").Rule} */
|
||||||
|
let Rule;
|
||||||
|
/** @type {typeof import("./sandbox.js").Sandbox} */
|
||||||
|
let Sandbox;
|
||||||
|
|
||||||
|
/** @typedef {import("./sandbox.js").AccessAction} AccessAction */
|
||||||
|
/** @typedef {import("./sandbox.js").Domain} Domain */
|
||||||
|
/** @typedef {import("./sandbox.js").Marshal} Marshal */
|
||||||
|
/** @typedef {import("./sandbox.js").Monitor} Monitor */
|
||||||
|
/** @typedef {import("./sandbox.js").Rule} Rule */
|
||||||
|
/** @typedef {import("./sandbox.js").Sandbox} Sandbox */
|
||||||
|
|
||||||
|
/** @type {boolean} */
|
||||||
let initialized = false;
|
let initialized = false;
|
||||||
|
/** @type {Sandbox} */
|
||||||
|
let defaultSandbox;
|
||||||
|
|
||||||
/** @type {Array<Sandbox>} */
|
/** @type {Array<Sandbox>} */
|
||||||
const sandboxStack = [];
|
const sandboxStack = [];
|
||||||
|
|
||||||
|
// 沙盒Function类型缓存
|
||||||
/** @type {WeakMap<Sandbox, Array<typeof Function>>} */
|
/** @type {WeakMap<Sandbox, Array<typeof Function>>} */
|
||||||
const isolatedsMap = new WeakMap();
|
const isolatedsMap = new WeakMap();
|
||||||
|
|
||||||
|
@ -46,6 +70,16 @@ const polyfills = {
|
||||||
namespaces: {},
|
namespaces: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 被封装的Function类型
|
||||||
|
/** @type {typeof Function} */
|
||||||
|
let ModFunction;
|
||||||
|
/** @type {typeof Function} */
|
||||||
|
let ModGeneratorFunction;
|
||||||
|
/** @type {typeof Function} */
|
||||||
|
let ModAsyncFunction;
|
||||||
|
/** @type {typeof Function} */
|
||||||
|
let ModAsyncGeneratorFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ```plain
|
* ```plain
|
||||||
* 将一个沙盒作为当前联网传输的运行沙盒
|
* 将一个沙盒作为当前联网传输的运行沙盒
|
||||||
|
@ -283,7 +317,12 @@ function _exec2(x, scope = {}) {
|
||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
function initSecurity({
|
/**
|
||||||
|
* ```plain
|
||||||
|
* 初始化模块
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
async function initSecurity({
|
||||||
lib,
|
lib,
|
||||||
game,
|
game,
|
||||||
ui,
|
ui,
|
||||||
|
@ -295,6 +334,15 @@ function initSecurity({
|
||||||
if (initialized)
|
if (initialized)
|
||||||
throw "security 已经被初始化过了";
|
throw "security 已经被初始化过了";
|
||||||
|
|
||||||
|
const sandbox = await import("./sandbox.js");
|
||||||
|
SANDBOX_ENABLED = sandbox.SANDBOX_ENABLED;
|
||||||
|
AccessAction = sandbox.AccessAction;
|
||||||
|
Domain = sandbox.Domain;
|
||||||
|
Marshal = sandbox.Marshal;
|
||||||
|
Monitor = sandbox.Monitor;
|
||||||
|
Rule = sandbox.Rule;
|
||||||
|
Sandbox = sandbox.Sandbox;
|
||||||
|
|
||||||
topVariables.lib = lib;
|
topVariables.lib = lib;
|
||||||
topVariables.game = game;
|
topVariables.game = game;
|
||||||
topVariables.ui = ui;
|
topVariables.ui = ui;
|
||||||
|
@ -307,11 +355,7 @@ function initSecurity({
|
||||||
return;
|
return;
|
||||||
|
|
||||||
loadPolyfills();
|
loadPolyfills();
|
||||||
|
initIsolatedEnvironment();
|
||||||
// @ts-ignore
|
|
||||||
Object.assign(defaultSandbox.scope, topVariables);
|
|
||||||
// @ts-ignore
|
|
||||||
setupPolyfills(defaultSandbox);
|
|
||||||
|
|
||||||
// 不允许被远程代码访问的game函数
|
// 不允许被远程代码访问的game函数
|
||||||
const ioFuncs = [
|
const ioFuncs = [
|
||||||
|
@ -510,6 +554,181 @@ function getIsolateds(sandbox) {
|
||||||
return isolateds.slice();
|
return isolateds.slice();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ```plain
|
||||||
|
* 根据传入对象的运行域获取对应的Function类型
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param {Object} item
|
||||||
|
* @returns {Array<typeof Function>}
|
||||||
|
*/
|
||||||
|
function getIsolatedsFrom(item) {
|
||||||
|
const domain = Marshal.getMarshalledDomain(item) || Domain.caller;
|
||||||
|
|
||||||
|
// 非顶级域调用情况下我们替换掉Function类型
|
||||||
|
if (domain && domain !== Domain.topDomain) {
|
||||||
|
const box = Sandbox.from(domain);
|
||||||
|
|
||||||
|
if (!box)
|
||||||
|
throw "意外的运行域: 运行域没有绑定沙盒";
|
||||||
|
|
||||||
|
return getIsolateds(box);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
ModFunction,
|
||||||
|
ModGeneratorFunction,
|
||||||
|
ModAsyncFunction,
|
||||||
|
ModAsyncGeneratorFunction,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ```plain
|
||||||
|
* 导入 `sandbox.js` 的相关类
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @returns {{
|
||||||
|
* AccessAction: typeof import("./sandbox.js").AccessAction,
|
||||||
|
* Domain: typeof import("./sandbox.js").Domain,
|
||||||
|
* Marshal: typeof import("./sandbox.js").Marshal,
|
||||||
|
* Monitor: typeof import("./sandbox.js").Monitor,
|
||||||
|
* Rule: typeof import("./sandbox.js").Rule,
|
||||||
|
* Sandbox: typeof import("./sandbox.js").Sandbox,
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
function importSandbox() {
|
||||||
|
if (!AccessAction)
|
||||||
|
throw new ReferenceError("sandbox.js 还没有被载入");
|
||||||
|
|
||||||
|
return {
|
||||||
|
AccessAction,
|
||||||
|
Domain,
|
||||||
|
Marshal,
|
||||||
|
Monitor,
|
||||||
|
Rule,
|
||||||
|
Sandbox,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ```plain
|
||||||
|
* 初始化顶级域的Funcion类型封装
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
function initIsolatedEnvironment() {
|
||||||
|
/** @type {typeof Function} */
|
||||||
|
// @ts-ignore
|
||||||
|
const defaultFunction = function () { }.constructor;
|
||||||
|
/** @type {typeof Function} */
|
||||||
|
// @ts-ignore
|
||||||
|
const defaultGeneratorFunction = function* () { }.constructor;
|
||||||
|
/** @type {typeof Function} */
|
||||||
|
// @ts-ignore
|
||||||
|
const defaultAsyncFunction = async function () { }.constructor;
|
||||||
|
/** @type {typeof Function} */
|
||||||
|
// @ts-ignore
|
||||||
|
const defaultAsyncGeneratorFunction = async function* () { }.constructor;
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
defaultSandbox = createSandbox(); // 所有 eval、parsex 代码全部丢进去喵
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
// 对于 defaultSandbox 我们要补充一些东西喵
|
||||||
|
defaultSandbox.scope.localStorage = localStorage;
|
||||||
|
|
||||||
|
// 对Function类型进行包裹
|
||||||
|
/** @type {Array<typeof Function>} */
|
||||||
|
const [
|
||||||
|
IsolatedFunction,
|
||||||
|
IsolatedGeneratorFunction,
|
||||||
|
IsolatedAsyncFunction,
|
||||||
|
IsolatedAsyncGeneratorFunction,
|
||||||
|
]
|
||||||
|
// @ts-ignore
|
||||||
|
= getIsolateds(defaultSandbox);
|
||||||
|
|
||||||
|
// 封装Function类型
|
||||||
|
|
||||||
|
ModFunction = new Proxy(defaultFunction, {
|
||||||
|
apply(target, thisArg, argumentsList) {
|
||||||
|
if (!sandBoxRequired)
|
||||||
|
return new target(...argumentsList);
|
||||||
|
|
||||||
|
return new IsolatedFunction(...argumentsList);
|
||||||
|
},
|
||||||
|
construct(target, argumentsList, newTarget) {
|
||||||
|
if (!sandBoxRequired)
|
||||||
|
return new target(...argumentsList);
|
||||||
|
|
||||||
|
return new IsolatedFunction(...argumentsList);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/** @type {typeof Function} */
|
||||||
|
ModGeneratorFunction = new Proxy(defaultGeneratorFunction, {
|
||||||
|
apply(target, thisArg, argumentsList) {
|
||||||
|
if (!sandBoxRequired)
|
||||||
|
return new target(...argumentsList);
|
||||||
|
|
||||||
|
return new IsolatedGeneratorFunction(...argumentsList);
|
||||||
|
},
|
||||||
|
construct(target, argumentsList, newTarget) {
|
||||||
|
if (!sandBoxRequired)
|
||||||
|
return new target(...argumentsList);
|
||||||
|
|
||||||
|
return new IsolatedGeneratorFunction(...argumentsList);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/** @type {typeof Function} */
|
||||||
|
ModAsyncFunction = new Proxy(defaultAsyncFunction, {
|
||||||
|
apply(target, thisArg, argumentsList) {
|
||||||
|
if (!sandBoxRequired)
|
||||||
|
return new target(...argumentsList);
|
||||||
|
|
||||||
|
return new IsolatedAsyncFunction(...argumentsList);
|
||||||
|
},
|
||||||
|
construct(target, argumentsList, newTarget) {
|
||||||
|
if (!sandBoxRequired)
|
||||||
|
return new target(...argumentsList);
|
||||||
|
|
||||||
|
return new IsolatedAsyncFunction(...argumentsList);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/** @type {typeof Function} */
|
||||||
|
ModAsyncGeneratorFunction = new Proxy(defaultAsyncGeneratorFunction, {
|
||||||
|
apply(target, thisArg, argumentsList) {
|
||||||
|
if (!sandBoxRequired)
|
||||||
|
return new target(...argumentsList);
|
||||||
|
|
||||||
|
return new IsolatedAsyncGeneratorFunction(...argumentsList);
|
||||||
|
},
|
||||||
|
construct(target, argumentsList, newTarget) {
|
||||||
|
if (!sandBoxRequired)
|
||||||
|
return new target(...argumentsList);
|
||||||
|
|
||||||
|
return new IsolatedAsyncGeneratorFunction(...argumentsList);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
function rewriteCtor(prototype, newCtor) {
|
||||||
|
const descriptor = Object.getOwnPropertyDescriptor(prototype, 'constructor')
|
||||||
|
|| { configurable: true, writable: true, enumerable: false };
|
||||||
|
if (!descriptor.configurable) throw new TypeError("无法覆盖不可配置的构造函数");
|
||||||
|
descriptor.value = newCtor;
|
||||||
|
Reflect.defineProperty(prototype, 'constructor', descriptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 覆盖所有的Function类型构造函数
|
||||||
|
window.Function = ModFunction;
|
||||||
|
rewriteCtor(defaultFunction.prototype, ModFunction);
|
||||||
|
rewriteCtor(defaultGeneratorFunction.prototype, ModGeneratorFunction);
|
||||||
|
rewriteCtor(defaultAsyncFunction.prototype, ModAsyncFunction);
|
||||||
|
rewriteCtor(defaultAsyncGeneratorFunction.prototype, ModAsyncGeneratorFunction);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ```plain
|
* ```plain
|
||||||
* 加载当前的垫片函数
|
* 加载当前的垫片函数
|
||||||
|
@ -607,127 +826,6 @@ function setupPolyfills(sandbox) {
|
||||||
`, context);
|
`, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @type {typeof Function} */
|
|
||||||
// @ts-ignore
|
|
||||||
const defaultFunction = function () { }.constructor;
|
|
||||||
/** @type {typeof Function} */
|
|
||||||
// @ts-ignore
|
|
||||||
const defaultGeneratorFunction = function* () { }.constructor;
|
|
||||||
/** @type {typeof Function} */
|
|
||||||
// @ts-ignore
|
|
||||||
const defaultAsyncFunction = async function () { }.constructor;
|
|
||||||
/** @type {typeof Function} */
|
|
||||||
// @ts-ignore
|
|
||||||
const defaultAsyncGeneratorFunction = async function* () { }.constructor;
|
|
||||||
|
|
||||||
const defaultSandbox = createSandbox(); // 所有 eval、parsex 代码全部丢进去喵
|
|
||||||
|
|
||||||
if (SANDBOX_ENABLED) {
|
|
||||||
// @ts-ignore
|
|
||||||
// 对于 defaultSandbox 我们要补充一些东西喵
|
|
||||||
defaultSandbox.scope.localStorage = localStorage;
|
|
||||||
|
|
||||||
// 对Function类型进行包裹
|
|
||||||
/** @type {Array<typeof Function>} */
|
|
||||||
const [
|
|
||||||
IsolatedFunction,
|
|
||||||
IsolatedGeneratorFunction,
|
|
||||||
IsolatedAsyncFunction,
|
|
||||||
IsolatedAsyncGeneratorFunction,
|
|
||||||
]
|
|
||||||
// @ts-ignore
|
|
||||||
= getIsolateds(defaultSandbox);
|
|
||||||
|
|
||||||
/** @type {typeof Function} */
|
|
||||||
let ModFunction;
|
|
||||||
/** @type {typeof Function} */
|
|
||||||
let ModGeneratorFunction;
|
|
||||||
/** @type {typeof Function} */
|
|
||||||
let ModAsyncFunction;
|
|
||||||
/** @type {typeof Function} */
|
|
||||||
let ModAsyncGeneratorFunction;
|
|
||||||
|
|
||||||
// 封装Function类型
|
|
||||||
|
|
||||||
ModFunction = new Proxy(defaultFunction, {
|
|
||||||
apply(target, thisArg, argumentsList) {
|
|
||||||
if (!sandBoxRequired)
|
|
||||||
return new target(...argumentsList);
|
|
||||||
|
|
||||||
return new IsolatedFunction(...argumentsList);
|
|
||||||
},
|
|
||||||
construct(target, argumentsList, newTarget) {
|
|
||||||
if (!sandBoxRequired)
|
|
||||||
return new target(...argumentsList);
|
|
||||||
|
|
||||||
return new IsolatedFunction(...argumentsList);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
/** @type {typeof Function} */
|
|
||||||
ModGeneratorFunction = new Proxy(defaultGeneratorFunction, {
|
|
||||||
apply(target, thisArg, argumentsList) {
|
|
||||||
if (!sandBoxRequired)
|
|
||||||
return new target(...argumentsList);
|
|
||||||
|
|
||||||
return new IsolatedGeneratorFunction(...argumentsList);
|
|
||||||
},
|
|
||||||
construct(target, argumentsList, newTarget) {
|
|
||||||
if (!sandBoxRequired)
|
|
||||||
return new target(...argumentsList);
|
|
||||||
|
|
||||||
return new IsolatedGeneratorFunction(...argumentsList);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
/** @type {typeof Function} */
|
|
||||||
ModAsyncFunction = new Proxy(defaultAsyncFunction, {
|
|
||||||
apply(target, thisArg, argumentsList) {
|
|
||||||
if (!sandBoxRequired)
|
|
||||||
return new target(...argumentsList);
|
|
||||||
|
|
||||||
return new IsolatedAsyncFunction(...argumentsList);
|
|
||||||
},
|
|
||||||
construct(target, argumentsList, newTarget) {
|
|
||||||
if (!sandBoxRequired)
|
|
||||||
return new target(...argumentsList);
|
|
||||||
|
|
||||||
return new IsolatedAsyncFunction(...argumentsList);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
/** @type {typeof Function} */
|
|
||||||
ModAsyncGeneratorFunction = new Proxy(defaultAsyncGeneratorFunction, {
|
|
||||||
apply(target, thisArg, argumentsList) {
|
|
||||||
if (!sandBoxRequired)
|
|
||||||
return new target(...argumentsList);
|
|
||||||
|
|
||||||
return new IsolatedAsyncGeneratorFunction(...argumentsList);
|
|
||||||
},
|
|
||||||
construct(target, argumentsList, newTarget) {
|
|
||||||
if (!sandBoxRequired)
|
|
||||||
return new target(...argumentsList);
|
|
||||||
|
|
||||||
return new IsolatedAsyncGeneratorFunction(...argumentsList);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
function rewriteCtor(prototype, newCtor) {
|
|
||||||
const descriptor = Object.getOwnPropertyDescriptor(prototype, 'constructor')
|
|
||||||
|| { configurable: true, writable: true, enumerable: false };
|
|
||||||
if (!descriptor.configurable) throw new TypeError("无法覆盖不可配置的构造函数");
|
|
||||||
descriptor.value = newCtor;
|
|
||||||
Reflect.defineProperty(prototype, 'constructor', descriptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 覆盖所有的Function类型构造函数
|
|
||||||
window.Function = ModFunction;
|
|
||||||
rewriteCtor(defaultFunction.prototype, ModFunction);
|
|
||||||
rewriteCtor(defaultGeneratorFunction.prototype, ModGeneratorFunction);
|
|
||||||
rewriteCtor(defaultAsyncFunction.prototype, ModAsyncFunction);
|
|
||||||
rewriteCtor(defaultAsyncGeneratorFunction.prototype, ModAsyncGeneratorFunction);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 测试暴露喵
|
// 测试暴露喵
|
||||||
// window.sandbox = defaultSandbox;
|
// window.sandbox = defaultSandbox;
|
||||||
|
|
||||||
|
@ -739,6 +837,8 @@ const exports = {
|
||||||
isUnsafeObject,
|
isUnsafeObject,
|
||||||
assertSafeObject,
|
assertSafeObject,
|
||||||
getIsolateds,
|
getIsolateds,
|
||||||
|
getIsolatedsFrom,
|
||||||
|
importSandbox,
|
||||||
requireSandbox,
|
requireSandbox,
|
||||||
requireSandboxOn,
|
requireSandboxOn,
|
||||||
isSandboxRequired,
|
isSandboxRequired,
|
||||||
|
|
Loading…
Reference in New Issue