Merge pull request #1401 from IceCola97/sandbox-dev
补充一个sandbox的问题;同时为调试模式和苹果设备放宽;适配eruda
This commit is contained in:
commit
50083b3a07
|
@ -125,9 +125,6 @@ export async function boot() {
|
|||
// 加载polyfill内容
|
||||
await import("./polyfill.js");
|
||||
|
||||
// 初始化沙盒的Realms
|
||||
await initializeSandboxRealms();
|
||||
|
||||
// 设定游戏加载时间,超过时间未加载就提醒
|
||||
const configLoadTime = localStorage.getItem(lib.configprefix + "loadtime");
|
||||
// 现在不暴露到全局变量里了,直接传给onload
|
||||
|
@ -248,13 +245,6 @@ export async function boot() {
|
|||
}
|
||||
}
|
||||
|
||||
// 初始化security
|
||||
const securityModule = await import("../util/security.js");
|
||||
const security = securityModule.default;
|
||||
security.initSecurity({
|
||||
lib, game, ui, get, ai, _status, gnc,
|
||||
});
|
||||
|
||||
const loadCssPromise = loadCss();
|
||||
const loadConfigPromise = loadConfig();
|
||||
await loadCssPromise;
|
||||
|
@ -303,6 +293,18 @@ export async function boot() {
|
|||
}
|
||||
}
|
||||
|
||||
const sandboxEnabled = !config.get("debug") && !get.is.safari();
|
||||
|
||||
// 初始化沙盒的Realms
|
||||
await initializeSandboxRealms(sandboxEnabled);
|
||||
|
||||
// 初始化security
|
||||
const securityModule = await import("../util/security.js");
|
||||
const security = securityModule.default;
|
||||
security.initSecurity({
|
||||
lib, game, ui, get, ai, _status, gnc,
|
||||
});
|
||||
|
||||
if (Reflect.get(window, "isNonameServer")) config.set("mode", "connect");
|
||||
|
||||
var pack = Reflect.get(window, "noname_package");
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// 为了兼容无法使用顶级await的版本
|
||||
const iframe = document.createElement("iframe");
|
||||
// 方便开关确定沙盒的问题喵
|
||||
// 当此处为true、debug模式为启用、设备非苹果时,沙盒生效
|
||||
let SANDBOX_ENABLED = true;
|
||||
|
||||
// 执行上下文传递函数,请勿动喵
|
||||
// 用于传递顶级execute context
|
||||
|
@ -38,7 +39,12 @@ function replaceName(path, name) {
|
|||
const TARGET_URL = replaceName(import.meta.url, "sandbox.js");
|
||||
const SANDBOX_EXPORT = {};
|
||||
|
||||
async function initializeSandboxRealms() {
|
||||
async function initializeSandboxRealms(enabled) {
|
||||
if (!enabled) {
|
||||
SANDBOX_ENABLED = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const document = window.document;
|
||||
const createElement = document.createElement.bind(document);
|
||||
const appendChild = document.body.appendChild.bind(document.body);
|
||||
|
@ -86,10 +92,6 @@ async function initializeSandboxRealms() {
|
|||
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;
|
||||
|
@ -111,7 +113,12 @@ async function initializeSandboxRealms() {
|
|||
iframe.remove();
|
||||
}
|
||||
|
||||
function isSandboxEnabled() {
|
||||
return SANDBOX_ENABLED;
|
||||
}
|
||||
|
||||
export {
|
||||
initializeSandboxRealms,
|
||||
isSandboxEnabled,
|
||||
SANDBOX_EXPORT,
|
||||
};
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
// 最后为安全考虑,请遵守规范,尽量不要使用 `eval` 函数而是使用 `security.exec2` 来替代
|
||||
|
||||
import { SANDBOX_EXPORT } from "./initRealms.js";
|
||||
import { SANDBOX_EXPORT, isSandboxEnabled } from "./initRealms.js";
|
||||
|
||||
// 很重要的事情!
|
||||
// 请不要在在其他文件中import sandbox.js!
|
||||
|
@ -16,8 +16,8 @@ import { SANDBOX_EXPORT } from "./initRealms.js";
|
|||
|
||||
/** @typedef {any} Window */
|
||||
|
||||
// 方便开关确定沙盒的问题喵
|
||||
const SANDBOX_ENABLED = true;
|
||||
// 新的开关放到了 "./initRealms.js" 里面,请不要改动此处!
|
||||
const SANDBOX_ENABLED = isSandboxEnabled();
|
||||
|
||||
// 暴露方法Symbol,用于类之间通信
|
||||
const SandboxExposer = Symbol("Sandbox.Exposer"); // 实例暴露
|
||||
|
@ -382,6 +382,7 @@ const GLOBAL_PATHES = Object.freeze([
|
|||
"/WeakRef",
|
||||
"/WeakMap",
|
||||
"/WeakSet",
|
||||
["/Object/Symbol(Symbol.hasInstance)", "Object[Symbol.hasInstance]"],
|
||||
"/Object/prototype",
|
||||
"/Array/prototype",
|
||||
"/Function/prototype",
|
||||
|
@ -2220,7 +2221,6 @@ class Marshal {
|
|||
cloned = {};
|
||||
|
||||
Reflect.setPrototypeOf(cloned, null);
|
||||
cloned["target"] = src;
|
||||
return cloned;
|
||||
}
|
||||
|
||||
|
@ -2293,12 +2293,14 @@ class Marshal {
|
|||
|
||||
// 创建一个空白对象,防止JavaScript的一些奇怪错误
|
||||
const pure = Marshal.#clonePureObject(target);
|
||||
// 设置属性方便调试
|
||||
pure.sourceDomain = sourceDomain;
|
||||
pure.targetDomain = targetDomain;
|
||||
|
||||
// 创建封送代理
|
||||
const proxy = new Proxy(pure, {
|
||||
// 设置属性方便调试
|
||||
// @ts-ignore
|
||||
$target: target,
|
||||
$sourceDomain: sourceDomain,
|
||||
$targetDomain: targetDomain,
|
||||
apply(_, thisArg, argArray) {
|
||||
const defaultApply = () => {
|
||||
const marshalledThis = Marshal.#marshal(thisArg, sourceDomain);
|
||||
|
@ -2400,7 +2402,19 @@ class Marshal {
|
|||
return !!dispatched.returnValue;
|
||||
|
||||
// @ts-ignore
|
||||
return Reflect.defineProperty(...args);
|
||||
const success = Reflect.defineProperty(...args);
|
||||
|
||||
if (success && target === args[0]) {
|
||||
// 为适配JavaScript对于代理的强制要求
|
||||
// 我们要对空白对象模拟不可配置
|
||||
// @ts-ignore
|
||||
attributes = Reflect.getOwnPropertyDescriptor(...args);
|
||||
|
||||
if (!attributes.configurable)
|
||||
Reflect.defineProperty(pure, args[1], attributes);
|
||||
}
|
||||
|
||||
return success;
|
||||
};
|
||||
|
||||
// `defineProperty`、`getOwnPropertyDescriptor`、`has` 都可能被JavaScript引擎重复调用
|
||||
|
@ -2587,7 +2601,18 @@ class Marshal {
|
|||
return !!dispatched.returnValue;
|
||||
|
||||
// @ts-ignore
|
||||
return Reflect.preventExtensions(...args);
|
||||
const success = Reflect.preventExtensions(...args);
|
||||
|
||||
if (success && target === args[0]) {
|
||||
// 为适配JavaScript对于代理的强制要求
|
||||
// 我们要对空白对象进行模拟键
|
||||
Reflect.ownKeys(target).forEach(key => {
|
||||
pure[key] = undefined;
|
||||
});
|
||||
Reflect.preventExtensions(pure);
|
||||
}
|
||||
|
||||
return success;
|
||||
});
|
||||
},
|
||||
set(_, p, newValue, receiver) {
|
||||
|
@ -3212,29 +3237,50 @@ class Sandbox {
|
|||
rewriteCtor(defaultAsyncGeneratorFunction.prototype, new Proxy(defaultAsyncGeneratorFunction, handler));
|
||||
}
|
||||
|
||||
// /**
|
||||
// * ```plain
|
||||
// * 替代原本的eval函数,阻止访问原生的 window 对象
|
||||
// * ```
|
||||
// *
|
||||
// * @param {Window} trueWindow
|
||||
// * @param {(x: string) => any} _eval
|
||||
// * @param {Proxy} intercepter
|
||||
// * @param {Window} global
|
||||
// * @param {any} x
|
||||
// */
|
||||
// static #wrappedEval = function (trueWindow, _eval, intercepter, global, x) {
|
||||
// const intercepterName = Sandbox.#makeName("_", trueWindow);
|
||||
// const evalName = Sandbox.#makeName("_", global);
|
||||
// const codeName = Sandbox.#makeName("_", global);
|
||||
// trueWindow[intercepterName] = intercepter;
|
||||
// global[evalName] = _eval;
|
||||
// global[codeName] = x;
|
||||
// const result = _eval(`with(${intercepterName}){with(window){${evalName}(\`"use strict";\${${codeName}}\`)}}`);
|
||||
// delete global[codeName];
|
||||
// delete global[evalName];
|
||||
// delete trueWindow[intercepterName];
|
||||
// return result;
|
||||
// }
|
||||
|
||||
/**
|
||||
* ```plain
|
||||
* 替代原本的eval函数,阻止访问原生的 window 对象
|
||||
* ```
|
||||
*
|
||||
* @param {Window} trueWindow
|
||||
* @param {(x: string) => any} _eval
|
||||
* @param {Proxy} intercepter
|
||||
* @param {Window} global
|
||||
* @param {Sandbox} thiz
|
||||
* @param {any} x
|
||||
* @returns
|
||||
*/
|
||||
static #wrappedEval = function (trueWindow, _eval, intercepter, global, x) {
|
||||
const intercepterName = Sandbox.#makeName("_", trueWindow);
|
||||
const evalName = Sandbox.#makeName("_", global);
|
||||
const codeName = Sandbox.#makeName("_", global);
|
||||
trueWindow[intercepterName] = intercepter;
|
||||
global[evalName] = _eval;
|
||||
global[codeName] = x;
|
||||
const result = _eval(`with(${intercepterName}){with(window){${evalName}("use strict;"+${codeName})}}`);
|
||||
delete global[codeName];
|
||||
delete global[evalName];
|
||||
delete trueWindow[intercepterName];
|
||||
return result;
|
||||
static #wrappedEval = function (thiz, x) {
|
||||
let code = String(x).trim();
|
||||
|
||||
while (code.endsWith(";"))
|
||||
code = code.slice(0, -1);
|
||||
|
||||
if (!/[;\n\r]$/.test(code))
|
||||
code = `return (${code})`;
|
||||
|
||||
return thiz.exec(code);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3476,7 +3522,7 @@ class Sandbox {
|
|||
let argumentList;
|
||||
let wrappedEval;
|
||||
|
||||
const raw = new thiz.#domainFunction("_", `with(_){with(window){with(${contextName}){return(()=>{"use strict";return(${applyName}(function(${parameters}){\n// 沙盒代码起始\n${code}\n// 沙盒代码结束\n},${contextName}.this,${argsName}))})()}}}`);
|
||||
const raw = new thiz.#domainFunction("_", `with(_){with(window){with(${contextName}){return(${applyName}(function(${parameters}){"use strict";\n// 沙盒代码起始\n${code}\n// 沙盒代码结束\n},${contextName}.this,${argsName}))}}}`);
|
||||
|
||||
const domain = thiz.#domain;
|
||||
const domainWindow = thiz.#domainWindow;
|
||||
|
@ -3520,8 +3566,9 @@ class Sandbox {
|
|||
},
|
||||
});
|
||||
|
||||
wrappedEval = Sandbox.#wrappedEval.bind(null,
|
||||
thiz.#domainWindow, thiz.#domainEval, intercepter, scope);
|
||||
// wrappedEval = Sandbox.#wrappedEval.bind(null,
|
||||
// thiz.#domainWindow, thiz.#domainEval, intercepter, scope);
|
||||
wrappedEval = Sandbox.#wrappedEval.bind(null, thiz);
|
||||
|
||||
// 构建陷入的沙盒闭包
|
||||
// 同时对返回值进行封送
|
||||
|
|
Loading…
Reference in New Issue