wilsons 发表于 2025-8-14 13:50:01

关于grant none/unsafeWindow之疑惑

看官方教程

(https://learn.scriptcat.org/%E6%B2%B9%E7%8C%B4%E6%95%99%E7%A8%8B/%E5%85%A5%E9%97%A8%E7%AF%87/grant%E4%BB%8B%E7%BB%8D,none%E4%B8%8EunsafeWindow/)

[沙盒机制的前世今生](https://learn.scriptcat.org/%E6%B2%B9%E7%8C%B4%E6%95%99%E7%A8%8B/%E5%85%A5%E9%97%A8%E7%AF%87/%E6%B2%99%E7%9B%92%E6%9C%BA%E5%88%B6%E7%9A%84%E5%89%8D%E4%B8%96%E4%BB%8A%E7%94%9F/)

或者网上搜索教程或者问AI

都说的头头是道,感觉似乎懂了,但一测试就懵逼了😳

这里汇总教程的大意是:

1. grant none 是脚本直接运行在前端页面中,此时可以访问页面中的原有变量,可以访问页面元素,但不能访问GM_*系列函数

2. 默认(即无none和unsafeWindow的情况下),运行在沙盒中,无法访问页面中的原有变量,可以访问页面元素,可以访问GM_*系列函数

3. grant unsafeWindow是运行在沙盒中,可以通过unsafeWindow访问页面中的原有变量,可以访问页面元素,可以访问GM_*系列函数

总结如下:
!(data/attachment/forum/202508/14/133355nlmbz306crlg4165.png)

但,我测试下来,却完全不是这样,什么默认,grant none,grant unsafeWindow效果完全一样。

以下是测试代码:

**网页代码如下**
```html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
      <title></title>
    </head>
   
    <body>
      <div id="dom1">dom 1</div>
      <button id="closePage">关闭页面</button>
      <script>
            var a=1;
            window.b=2;
            c=3;
            let d=4;
            const e = 5;
      </script>
    </body>
</html>
```

在线地址 [https://wilson.lovestoblog.com/demo/scriptcat_demo.html](https://wilson.lovestoblog.com/demo/scriptcat_demo.html)

**油猴代码如下**
```js
// ==UserScript==
// @name         Demo
// @namespace    https://bbs.tampermonkey.net.cn/
// @version      0.1.0
// @descriptiontry to take over the world!
// @author       You
// @match      *://*/*
// ==/UserScript==

console.log('---> demoooooooooooooooooooo start <---')
console.log('变量', {a,b,c,d,e});
console.log('dom', document.querySelector('#dom1'));
document.querySelector('#closePage').addEventListener('click', ()=>window.close());
console.log('---> demoooooooooooooooooooo end <---')
```
注意,这里div id 是 dom1 不是demo1,别看错了!

**浏览器打印结果**(无论默认,grant none,grant unsafeWindow效果完全一样)
!(data/attachment/forum/202508/14/134415zj758awj7bn8wr8r.png)

所以,**我的疑惑是:我理解错了吗?还是测试错了?还是教程错了?** 懵逼。。。

王一之 发表于 2025-8-14 13:50:02

教程有一些问题,你来听我狡辩一下:

目前的沙盒是一个半沙盒的情况,教程中描述的是全沙盒的情况,教程是我最开始编写的,可能有些问题。

目前的半沙盒是: 沙盒中可以访问外面的变量(除了一些特殊定义的以外:例如`define`、`export`),但是外面的变量不能到沙盒里面来,如果你在沙盒内定义`window.b=100`,在页面上访问b还是为2。


脚本猫最近的一次重构沙盒,里面有很多细节,有兴趣可以看看
https://github.com/scriptscat/scriptcat/pull/524

```js
// ==UserScript==
// @name         Demo
// @namespace    https://bbs.tampermonkey.net.cn/
// @version      0.1.0
// @descriptiontry to take over the world!
// @author       You
// @match      *://*/*
// @grant      unsafeWindow
// ==/UserScript==

console.log('---> demoooooooooooooooooooo start <---')
console.log('变量', { a, b, c, d, e });
console.log('dom', document.querySelector('#dom1'));
document.querySelector('#closePage').addEventListener('click', () => window.close());
console.log('---> demoooooooooooooooooooo end <---')

a = 2;
b = 3;
c = 4;
d = 5;
// e是常量,不能修改
// e = 6;

console.log(window, this);

window.b = 100;

console.log('变量', { a, b, c, d, e });
```

王一之 发表于 2025-8-14 15:23:00

我修改了一下教程内容,有什么疑问哥哥可以继续提出,我也好再次进行修改

----

## none和unsafeWindow

简单来说:
`none`就是直接运行在前端页面中,否则就是运行在一个沙盒环境,需要使用`unsafeWindow`去操作前端的元素。

除了`GM_*` 函数外,还有两个特殊的权限,就是`none`和`unsafeWindow`。

默认情况下,你的脚本运行在油猴给你创建的一个半沙盒环境中,在这个沙盒环境中,你可以访问到页面上的元素,但是页面上的元素无法访问到脚本中的内容,用来隔离两个环境。

```js
b = 123;// 脚本中未定义b,会击穿沙盒到页面中去,此时:window.b=undefind,unsafeWindow=123;
console.log(window.b, unsafeWindow.b);
window.b = 234;// 在脚本的window中定义b,后续对b的操作都是在脚本的上下文中进行的,此时:window.b=234,unsafeWindow=123;
console.log(window.b, unsafeWindow.b);
b = 345; // 已经在脚本上下文中定义b了,效果同上,此时:window.b=345,unsafeWindow=123;
console.log(window.b, unsafeWindow.b);
unsafeWindow.b = 456; // 这里操作的是页面的对象,此时:window.b=345,unsafeWindow.b=456;
console.log(window.b, unsafeWindow.b);
```

wilsons 发表于 2025-8-14 15:43:44

本帖最后由 wilsons 于 2025-8-15 11:34 编辑

> 本帖最后由 wilsons 于 2025-8-15 11:32 编辑

> 本帖最后由 wilsons 于 2025-8-15 11:17 编辑

> [王一之 发表于 2025-8-14 15:02](forum.php?mod=redirect&goto=findpost&pid=99547&ptid=9347)
> > 教程有一些问题,你来听我狡辩一下:

目前的沙盒是一个半沙盒的情况,教程中描述的是全沙盒的情况,教 ...

感谢大佬!学习了!

我测试了下,总结如下:

1. 沙盒可以访问页面中的变量。
2. 页面不能访问沙盒中的变量,但隐式全局变量(未声明变量的变量)除外,比如,m=1,这相当于unsafeWindow.m=1,但严格模式下会报错,闭包下也无效。
3. 当油猴脚本grant none 时,window.xxx 可以修改页面中变量的值,此时油猴脚本中unsafeWindow是未定义。
4. 当油猴脚本默认或grant unsafeWindow时,window.xxx 不能修改页面中变量的值,但unsafeWindow.xxx可以修改页面变量的值。

测试代码如下:

页面代码
```html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
      <title></title>
    </head>
   
    <body>
      <div id="dom1">dom 1</div>
      <button id="closePage">关闭页面</button>
      <script>
            var a=1;
            window.b=2;
            c=3;
            let d=4;
            const e = 5;
            
            setTimeout(()=>{
                console.log('4秒后页面访问沙盒的变量', { a, b, c, d, e })
                console.log('---> demoooooooooooooooooooo end2 <---')
            }, 4000)
      </script>
    </body>
</html>
```

油猴脚本代码
```js
// ==UserScript==
// @name         Demo
// @namespace    https://bbs.tampermonkey.net.cn/
// @version      0.1.0
// @descriptiontry to take over the world!
// @author       You
// @match      *://*/*
// ==/UserScript==

console.log('---> demoooooooooooooooooooo start <---')
console.log('变量', {a,b,c,d,e});
console.log('dom', document.querySelector('#dom1'));
document.querySelector('#closePage').addEventListener('click', ()=>window.close());
console.log('---> demoooooooooooooooooooo end <---')

a = 2;
b = 3;
c = 4;
d = 5;
// e是常量,不能修改
// e = 6;

window.b = 100; // @grant none 时生效
unsafeWindow.b = 200; // 默认和@grant unsafeWindow时生效
```

wilsons 发表于 2025-8-14 15:49:35

王一之 发表于 2025-8-14 15:23
我修改了一下教程内容,有什么疑问哥哥可以继续提出,我也好再次进行修改

----

感谢大佬!学习了!

我刚才看了教程,感觉有些抽象,新手不容易理解。

我觉得可以像我这个帖子中那样描述,页面中有什么变量,油猴脚本中如何访问,反过来,油猴有哪些变量,页面中如何访问等,这样去描述可能更清晰点。

王一之 发表于 2025-8-14 15:51:49

wilsons 发表于 2025-8-14 15:49
感谢大佬!学习了!

我刚才看了教程,感觉有些抽象,新手不容易理解。


已经更新过去了,有些地方哥哥也可以补充

确实有实例的话,会更好理解一些,但是没那么多精力维护,而且出发角度不同也不会考虑到那么多

wilsons 发表于 2025-8-14 15:55:22

王一之 发表于 2025-8-14 15:51
已经更新过去了,有些地方哥哥也可以补充

确实有实例的话,会更好理解一些,但是没那么多精力维护,而且 ...

ok!

大佬辛苦了!
页: [1]
查看完整版本: 关于grant none/unsafeWindow之疑惑