允许沙盒暴露基础的dom类型
This commit is contained in:
parent
0362369500
commit
fc82884048
|
@ -65,11 +65,11 @@ class CodeSnippet {
|
|||
* 获取当前代码片段
|
||||
* ```
|
||||
*
|
||||
* @type {CodeSnippet}
|
||||
* @type {CodeSnippet?}
|
||||
*/
|
||||
static get currentSnippet() {
|
||||
if (!this.#snippetStack.length)
|
||||
throw new Error("代码片段栈为空");
|
||||
return null;
|
||||
|
||||
return this.#snippetStack[this.#snippetStack.length - 1];
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ class ErrorReporter {
|
|||
/:(\d+):\d+/,
|
||||
];
|
||||
|
||||
/** @type {CodeSnippet} */
|
||||
/** @type {CodeSnippet?} */
|
||||
#snippet;
|
||||
/** @type {string} */
|
||||
#message;
|
||||
|
@ -128,7 +128,7 @@ class ErrorReporter {
|
|||
* ```
|
||||
*
|
||||
* @param {Error} error
|
||||
* @param {CodeSnippet} snippet
|
||||
* @param {CodeSnippet?} snippet
|
||||
*/
|
||||
constructor(error, snippet = CodeSnippet.currentSnippet) {
|
||||
if (!("stack" in error))
|
||||
|
@ -159,6 +159,9 @@ class ErrorReporter {
|
|||
}
|
||||
|
||||
viewCode() {
|
||||
if(!this.#snippet)
|
||||
return null;
|
||||
|
||||
const stack = this.#stack;
|
||||
const line = stack.split("\n")[1];
|
||||
const lineno = ErrorReporter.#findLineNo(line);
|
||||
|
|
|
@ -111,6 +111,8 @@ async function initializeSandboxRealms(enabled) {
|
|||
delete iframe.contentWindow.replacedCI2;
|
||||
// @ts-ignore
|
||||
delete iframe.contentWindow.replacedCIC;
|
||||
// @ts-ignore
|
||||
delete iframe.contentWindow.replacedErrors;
|
||||
|
||||
// @ts-ignore
|
||||
Object.assign(SANDBOX_EXPORT, iframe.contentWindow.SANDBOX_EXPORT);
|
||||
|
|
|
@ -2247,8 +2247,7 @@ class Marshal {
|
|||
if (descriptor
|
||||
&& descriptor.value
|
||||
&& !descriptor.enumerable
|
||||
&& !descriptor.configurable
|
||||
&& descriptor.value.constructor === src)
|
||||
&& !descriptor.configurable)
|
||||
cloned = function () { };
|
||||
else
|
||||
cloned = () => { };
|
||||
|
@ -2313,24 +2312,38 @@ class Marshal {
|
|||
|
||||
if (mappedCtor) {
|
||||
const newError = new mappedCtor();
|
||||
const stack = (function () {
|
||||
const silentAccess = (o, p, d) => {
|
||||
try {
|
||||
return String(target.stack);
|
||||
if (typeof p == "function")
|
||||
return p(o);
|
||||
else
|
||||
return o[p];
|
||||
} catch (e) {
|
||||
return "无法获取错误";
|
||||
return d;
|
||||
}
|
||||
})();
|
||||
};
|
||||
const pinValue = (o, p, v) => {
|
||||
Reflect.defineProperty(o, p, {
|
||||
get: () => v,
|
||||
set: () => { },
|
||||
configurable: false,
|
||||
});
|
||||
};
|
||||
|
||||
Reflect.defineProperty(newError, 'stack', {
|
||||
get: () => () => stack,
|
||||
set: () => { },
|
||||
configurable: false,
|
||||
});
|
||||
const name = String(silentAccess(target, "name", "#无法获取错误名#"));
|
||||
const message = String(silentAccess(target, "message", "#无法获取错误消息#"));
|
||||
const stack = String(silentAccess(target, "stack", "#无法获取调用栈#"));
|
||||
const string = silentAccess(target, String, "#无法获取错误信息#");
|
||||
|
||||
pinValue(newError, "name", name);
|
||||
pinValue(newError, "message", message);
|
||||
pinValue(newError, "stack", stack);
|
||||
pinValue(newError, "toString", () => string);
|
||||
|
||||
// 继承原本的错误信息
|
||||
const errorReporter = ErrorManager.getErrorReporter(target);
|
||||
if (errorReporter)
|
||||
ErrorManager.setErrorReporter(newError, errorReporter);
|
||||
ErrorManager.setErrorReporter(newError,
|
||||
errorReporter || new ErrorReporter(target)); // 无论有没有都捕获当前的错误信息
|
||||
|
||||
return newError;
|
||||
}
|
||||
|
@ -3164,6 +3177,10 @@ function trapMarshal(srcDomain, dstDomain, obj) {
|
|||
* ```
|
||||
*/
|
||||
class Sandbox {
|
||||
// @ts-ignore
|
||||
static #topWindow = window.replacedGlobal || window;
|
||||
// @ts-ignore
|
||||
static #topWindowHTMLElement = (window.replacedGlobal || window).HTMLElement;
|
||||
/** @type {WeakMap<Domain, Sandbox>} */
|
||||
static #domainMap = new WeakMap();
|
||||
/** @type {Array} */
|
||||
|
@ -3204,6 +3221,20 @@ class Sandbox {
|
|||
*/
|
||||
#freeAccess = false;
|
||||
|
||||
/**
|
||||
* ```plain
|
||||
* 当在当前scope中访问不到变量时,
|
||||
* 是否允许沙盒代码可以穿透到顶级域的全局变量域中
|
||||
* 去读取DOM类型的构造函数(仅读取)
|
||||
* (包括Image、Audio等)
|
||||
*
|
||||
* 此开关有风险,请谨慎使用
|
||||
* ```
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
#domAccess = false;
|
||||
|
||||
/**
|
||||
* 创建一个新的沙盒
|
||||
*/
|
||||
|
@ -3441,6 +3472,40 @@ class Sandbox {
|
|||
this.#freeAccess = !!value;
|
||||
}
|
||||
|
||||
/**
|
||||
* ```plain
|
||||
* 当在当前scope中访问不到变量时,
|
||||
* 是否允许沙盒代码可以穿透到顶级域的全局变量域中
|
||||
* 去读取DOM类型的构造函数(仅读取)
|
||||
* (包括Image、Audio等)
|
||||
*
|
||||
* 此开关有风险,请谨慎使用
|
||||
* ```
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
get domAccess() {
|
||||
Sandbox.#assertOperator(this);
|
||||
return this.#domAccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* ```plain
|
||||
* 当在当前scope中访问不到变量时,
|
||||
* 是否允许沙盒代码可以穿透到顶级域的全局变量域中
|
||||
* 去读取DOM类型的构造函数(仅读取)
|
||||
* (包括Image、Audio等)
|
||||
*
|
||||
* 此开关有风险,请谨慎使用
|
||||
* ```
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
set domAccess(value) {
|
||||
Sandbox.#assertOperator(this);
|
||||
this.#domAccess = !!value;
|
||||
}
|
||||
|
||||
/**
|
||||
* ```plain
|
||||
* 向当前域注入内建对象
|
||||
|
@ -3800,10 +3865,18 @@ class Sandbox {
|
|||
// 暴露非内建的顶级全局变量
|
||||
if (thiz.#freeAccess
|
||||
&& !Globals.isBuiltinKey(p)) {
|
||||
const topWindow = Domain.topDomain[SandboxExposer](SandboxSignal_GetWindow);
|
||||
const topWindow = Sandbox.#topWindow;
|
||||
|
||||
if (p in topWindow)
|
||||
return trapMarshal(Domain.topDomain, thiz.#domain, topWindow[p]);
|
||||
} else if (thiz.#domAccess) {
|
||||
const topWindow = Sandbox.#topWindow;
|
||||
const accessTarget = topWindow[p];
|
||||
|
||||
if (typeof accessTarget == "function"
|
||||
&& "prototype" in accessTarget
|
||||
&& accessTarget.prototype instanceof Sandbox.#topWindowHTMLElement)
|
||||
return trapMarshal(Domain.topDomain, thiz.#domain, accessTarget);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
|
@ -3816,6 +3889,14 @@ class Sandbox {
|
|||
&& !Globals.isBuiltinKey(p)) {
|
||||
const topWindow = Domain.topDomain[SandboxExposer](SandboxSignal_GetWindow);
|
||||
return p in topWindow;
|
||||
} else if (thiz.#domAccess) {
|
||||
const topWindow = Sandbox.#topWindow;
|
||||
const accessTarget = topWindow[p];
|
||||
|
||||
if (typeof accessTarget == "function"
|
||||
&& "prototype" in accessTarget
|
||||
&& accessTarget.prototype instanceof Sandbox.#topWindowHTMLElement)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -583,6 +583,7 @@ function createSandbox() {
|
|||
|
||||
const box = new Sandbox();
|
||||
box.freeAccess = true;
|
||||
box.domAccess = true;
|
||||
box.initBuiltins();
|
||||
|
||||
// 向沙盒提供顶级运行域的文档对象
|
||||
|
|
Loading…
Reference in New Issue