Skip to content

fix: 修正被破坏的沙盒 Fix Corrupted Sandbox#966

Merged
CodFrm merged 7 commits into
scriptscat:mainfrom
cyfung1031:pr-fix-sandbox-1300
Nov 17, 2025
Merged

fix: 修正被破坏的沙盒 Fix Corrupted Sandbox#966
CodFrm merged 7 commits into
scriptscat:mainfrom
cyfung1031:pr-fix-sandbox-1300

Conversation

@cyfung1031
Copy link
Copy Markdown
Collaborator

@cyfung1031 cyfung1031 commented Nov 15, 2025

概述 Descriptions

Close #962

腳本驗證

  1. [BUG] Steam Inventory Helper does not work in ScriptCat #737
    Install https://raw.githubusercontent.com/Nuklon/Steam-Economy-Enhancer/master/code.user.js
    Open https://steamcommunity.com/market/

测试用脚本:

https://www.ign.com/wikis/starcraft/Terran_Story

// ==UserScript==
// @name         Sandbox Test
// @namespace    https://bbs.tampermonkey.net.cn/
// @version      0.1.0
// @description  try to take over the world!
// @author       You
// @match        https://www.ign.com/wikis/starcraft/Terran_Story*
// @grant        unsafeWindow
// @grant        GM_info
// ==/UserScript==

/* global ChessKit */

const tag = GM_info.scriptHandler === "ScriptCat" ? "SC" : "TM";

const deferred = () => {
  let resolve;
  let reject;
  const promise = new Promise((res, rej) => {
    resolve = res;
    reject = rej;
  });
  return { promise, resolve, reject };
};

unsafeWindow[`sandboxTest${tag}`] = async function () {
    console.log(`---- ${tag} ----`);

    console.log("B1", `${window}` === "[object Window]");
    console.log("B2", typeof window.addEventListener === "function");
    console.log("B3", typeof window.dispatchEvent === "function");
    console.log("B4", typeof window.setTimeout === "function");
    console.log("B5", typeof window.requestAnimationFrame === "function");
    console.log("B6", window.addEventListener !== EventTarget.prototype.addEventListener);

    console.log("U1", typeof window.ChessKit === "undefined")
    console.log("U2", typeof (unsafeWindow.ChessKit?.props || "fail") === "object")
    console.log("U3", typeof ChessKit !== "undefined" && typeof (ChessKit?.props || "fail") === "object");

    console.log("X1", typeof window.constructor === "function");
    console.log("X2", window instanceof window.constructor === false);

    console.log("W1", window.__proto__ && window.__proto__ === unsafeWindow.__proto__);
    console.log("W2", window instanceof Window === false);
    console.log("W3", window instanceof EventTarget === false);
    console.log("W4", Object.getPrototypeOf(window) === null)

    const p1 = deferred();
    const p2 = deferred();

    const randomKey1 = `e${Math.round(Math.random() * 1e8 + 1e5).toString(36)}`;
    const randomKey2 = `e${Math.round(Math.random() * 1e8 + 1e5).toString(36)}`;

    window.addEventListener(randomKey1, function (evt) {
        p1.resolve(evt.target === unsafeWindow);
    });
    unsafeWindow.addEventListener(randomKey1, function (evt) {
        p2.resolve(evt.target === unsafeWindow);
    });

    window.dispatchEvent(new Event(randomKey1));
    unsafeWindow.dispatchEvent(new Event(randomKey1));

    const res = await Promise.all([p1.promise, p2.promise]);
    console.log("E1", res[0] === true);
    console.log("E2", res[1] === true);
    let methodErr;
    try{
        EventTarget.prototype.addEventListener.call(window, randomKey2, function(){
            console.log(123);
        });
        throw new Error("FAIL");
    }catch (e){
        methodErr = e;
    }
    console.log("E3", methodErr?.message !== "FAIL");
}

setTimeout(()=> unsafeWindow[`sandboxTest${tag}`](), 500);

变更内容 Changes

截图 Screenshots

@cyfung1031
Copy link
Copy Markdown
Collaborator Author

@CodFrm 这个算是Bug修正。我有脚本用 window instanceof window.constructor 来判断是否沙盒window
我先标P0

@cyfung1031 cyfung1031 added P0 🚑 需要紧急处理的内容 hotfix 需要尽快更新到扩展商店 labels Nov 15, 2025
@CodFrm CodFrm requested a review from Copilot November 16, 2025 05:29
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

本 PR 修复了沙盒环境中的关键问题(issue #962),使 ScriptCat 的沙盒行为与 TamperMonkey 保持一致。主要解决了 window 对象的原型链、构造函数和事件监听器的正确性问题。

主要变更:

  • 引入 PseudoWindow 类来正确模拟 Window 原型链,确保 window.constructor === Windowwindow instanceof Window === false
  • 修复了 descsCache 的使用,防止子类属性被父类属性覆盖
  • 调整测试环境设置,模拟真实浏览器的 Symbol.toStringTagEventTarget 行为

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.

File Description
src/app/service/content/create_context.ts 核心修复:引入 PseudoWindow 类和改进的沙盒初始化逻辑,修复 window 原型链问题
tests/vitest.setup.ts 测试环境增强:配置 Symbol.toStringTag 和 EventTarget 以匹配浏览器行为
src/app/service/content/exec_script.test.ts 测试更新:移除部分并发测试,添加 TM Sandbox Window 测试用例验证修复

Comment thread tests/vitest.setup.ts Outdated
Comment thread src/app/service/content/create_context.ts
Comment thread src/app/service/content/create_context.ts
Comment thread src/app/service/content/create_context.ts Outdated
Comment thread src/app/service/content/exec_script.test.ts
@cyfung1031 cyfung1031 changed the title 修正被破坏的沙盒 修正被破坏的沙盒 Fix Corrupted Sandbox Nov 16, 2025
@cyfung1031 cyfung1031 changed the title 修正被破坏的沙盒 Fix Corrupted Sandbox fix: 修正被破坏的沙盒 Fix Corrupted Sandbox Nov 16, 2025
@CodFrm CodFrm merged commit dd80386 into scriptscat:main Nov 17, 2025
3 checks passed
@CodFrm
Copy link
Copy Markdown
Member

CodFrm commented Nov 19, 2025

我似乎又遇到了一个沙盒问题,使用 Bilibili-Evolved 安装插件,下载视频,会出现下面这个错误,看起来是fetch没有.bind

image

https://www.bilibili.com/video/BV1zuxbzFEJd/

一个最小化可复现脚本:

// ==UserScript==
// @name         New Userscript E381-1
// @namespace    https://docs.scriptcat.org/
// @version      0.1.0
// @description  try to take over the world!
// @author       You
// @match        https://www.bilibili.com/video/BV1zuxbzFEJd/
// @icon         https://www.google.com/s2/favicons?sz=64&domain=www.bilibili.com
// @grant        unsafeWindow
// ==/UserScript==

fetch("https://bbs.tampermonkey.net.cn/")

@cyfung1031
Copy link
Copy Markdown
Collaborator Author

我看看

@cyfung1031
Copy link
Copy Markdown
Collaborator Author

cyfung1031 commented Nov 19, 2025

看起来是fetch没有.bind

找到原因,不是这个
是因为 fetch.call(window, ...)
window 不是真window 所以报错
看来TM有做特殊处理。 TM的 fetch.call(window, ...) 不会报错

也不對。。。不是這原因

我了解一下

@CodFrm
Copy link
Copy Markdown
Member

CodFrm commented Nov 19, 2025

看起来是fetch没有.bind

找到原因,不是这个 是因为 fetch.call(window, ...) window 不是真window 所以报错 看来TM有做特殊处理。 TM的 fetch.call(window, ...) 不会报错

也不對。。。不是這原因

我了解一下

我这里启用了 AdGuard 就会出现这个问题(扩展拿不到最原始的fetch),关闭这个问题就消失了(拿到了最原始的fetch),这个问题也好奇怪(TM也是如此)

之前也有因为 AdGuard 产生的问题: #773 (comment)

image
image
image

@CodFrm
Copy link
Copy Markdown
Member

CodFrm commented Nov 19, 2025

TM 可能是做了些什么特殊处理,TM的fech是bind了的:

image

@cyfung1031
Copy link
Copy Markdown
Collaborator Author

cyfung1031 commented Nov 19, 2025

#985

处理好了

你讲得没错。是没 bind 好

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

hotfix 需要尽快更新到扩展商店 P0 🚑 需要紧急处理的内容

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] 之前写好的 沙盒设计 因为被改动过而烂了

3 participants