Skip to content

优化 脚本执行方式#486

Closed
DreamNya wants to merge 0 commit intoscriptscat:mainfrom
DreamNya:Inject
Closed

优化 脚本执行方式#486
DreamNya wants to merge 0 commit intoscriptscat:mainfrom
DreamNya:Inject

Conversation

@DreamNya
Copy link
Contributor

@DreamNya DreamNya commented Jul 3, 2025

由于// @​run-at document-start的脚本对于执行时机非常敏感,原本无论// @​grant是否为none均要等待content.js进行初始化后才会执行

现在优化为同时满足// @​run-at document-start// @​grant none 的脚本在注入时立即执行,不再等待content.js

备注:
// @​run-at不为document-start的脚本对执行时机不敏感,无需优化
// @​grant不为none的脚本必须等待content.js初始化才可获取GMapicontent(sandbox)上下文,目前无合理优化方案

@CodFrm
Copy link
Member

CodFrm commented Jul 3, 2025

有几个问题:

1、GM_info没有注入进去
2、目前的匹配方式,对于无法处理的@match表达式,是采用通配的方式,这样会导致脚本可能会在任意页面上运行
3、如果需要的话,我认为不如新开一个@run-at去表述,另外强制要求只能使用@match且符合匹配模式规范

@DreamNya DreamNya marked this pull request as draft July 3, 2025 02:54
@CodFrm CodFrm force-pushed the main branch 2 times, most recently from 52766bd to 25fcffc Compare July 8, 2025 03:41
@cyfung1031
Copy link
Collaborator

cyfung1031 commented Jul 12, 2025

@DreamNya @CodFrm

这个就是VM的@unwrap
很常用的
有空我会提交相关PR

用途主要是,更快更直接操作页面
因为没有任何wrapping, let 都可以在页面上跑定义全域变数
(当然加了@unwrap后 await就不能直接用在top-level)

有一些小脚本就是要这样粗暴的网页修改,不用GM的功能

PR会按照VM的做法, 当 @unwrap 声明了,所有@grant 包括 @grant none 都会被无视,而且没有沙盒没有GM没有GM_info

因为TM脚本不会有这个@unwrap 所以能完全相容TM脚本


https://violentmonkey.github.io/api/metadata-block/

@unwrap
Since VM2.13.1.

If supplied, the script will be injected as is into the global scope of the page, i.e. without our standard wrapper like window.VMxxx=function(){...}.

The [@grant](https://violentmonkey.github.io/api/metadata-block/#grant) key is ignored so the script won’t have access to GM.* or GM_* API. The [@inject-into](https://violentmonkey.github.io/api/metadata-block/#inject-into) key is supported as usual.

A typical use case is direct access to global page variables declared as const or let. In a standard userscript you would have to create a script element yourself explicitly by using document.createElement or [GM_addElement](https://violentmonkey.github.io/api/gm/#gm_addelement), then transfer the result via a CustomEvent or unsafeWindow.foo.

Another use case is migration from other extensions that run your JavaScript code as is, without userscript API.

@cyfung1031
Copy link
Collaborator

现在的注入模式是
先抓脚本资料,然后分析(有GM资讯),再扔去inject.js那边
所以即使unwrap也只能做到 window[...] = function (){ ... } 这一层。
因为有GM资讯才有注入,所以不会因为拿走GM资讯就能加快注入

MV3的最大问题,没有好的网址配对脚本注入。没办法吧

@CodFrm
Copy link
Member

CodFrm commented Jul 12, 2025

这种注入模式,应该也有方法使用到GM API(可能就只能使用异步的了)

@CodFrm
Copy link
Member

CodFrm commented Jul 12, 2025

@cyfung1031 也许并不是@unwrap,这里的目标是让脚本更快的注入到页面当中去,甚至在页面没有加载好的时候,就将脚本注入,现在哪怕@run-at document-start都达不到这个速度,而不是不能使用任何GM API,与包装形式

@cyfung1031
Copy link
Collaborator

@cyfung1031 也许并不是@unwrap,这里的目标是让脚本更快的注入到页面当中去,甚至在页面没有加载好的时候,就将脚本注入,现在哪怕@run-at document-start都达不到这个速度,而不是不能使用任何GM API,与包装形式

有一段時間的 @run-at document-start 真的是在页面没有加载好就注入執行
也就是連 document.documentElement 都是 null 的
但現在好像沒有這樣了 (可能是TM?改成了MV3後就不能這樣?)

在MV3好像看不到這個可能性 (因為網址配對問題)

@CodFrm
Copy link
Member

CodFrm commented Jul 13, 2025

@cyfung1031 关于这个需求,可以看这里:

[活动结束][有奖答题]网页点击大挑战!2.0
https://bbs.tampermonkey.net.cn/thread-3487-1-1.html
(出处: 油猴中文网)

http://test-case.ggnb.top/is_trusted/is_trusted.html

QQ_1752374845374
// ==UserScript==
// @name         New Userscript
// @namespace    https://bbs.tampermonkey.net.cn/
// @version      0.1.0
// @description  try to take over the world!
// @author       You
// @match        http://test-case.ggnb.top/is_trusted/is_trusted.html
// @run-at       document_start
// ==/UserScript==

console.log("script running");

脚本始终慢页面js一步

@cyfung1031
Copy link
Collaborator

cyfung1031 commented Jul 13, 2025

@CodFrm

脚本始终慢页面js一步

要不要你在后台先把所有脚本的配对规则都拿出来
一看到有navigation request (没错,是要求载入而不是开始载入)
就把那个request的url记起来,(时间长的话在后台用worker配对,)然后配对后的结果发给后台处理注入那边
当脚本能用userscript api注入时,马上看一下注入哪些,然后注入

这样的话就省下了一堆content js inject js的沟通


再快一点的话,在navigation request的时候,分析完就用userscript API马上register. (知道那些脚本要注入,注入的网址)
那麼userscript api 可以在ScriptCat收到「脚本能用userscript api注入」之前就經userscript api注入了

@CodFrm
Copy link
Member

CodFrm commented Jul 13, 2025

@cyfung1031 这样还是做不到最快,因为始终需要处理一下value/resource之类的资源(pageLoad方法那里),想要达到这个效果,还是得依靠chrome.userScripts.register注入完成后,马上执行脚本

@cyfung1031
Copy link
Collaborator

@cyfung1031 这样还是做不到最快,因为始终需要处理一下value/resource之类的资源(pageLoad方法那里),想要达到这个效果,还是得依靠chrome.userScripts.register注入完成后,马上执行脚本

不做pageLoad

navigation request -> 後台配對那些腳本注入這個網址 -> chrome.userScripts.register( 網址, 腳本 )

@CodFrm
Copy link
Member

CodFrm commented Jul 13, 2025

@cyfung1031 这个流程听起来似乎也可以,后续再验证一下

@cyfung1031
Copy link
Collaborator

cyfung1031 commented Jul 13, 2025

@cyfung1031 这个流程听起来似乎也可以,后续再验证一下

离题一下:
现在SC的脚本运作比TM更稳定
TM有时候不知是不是开关扩充问题
会导致脚本配对失败无法运行
要重啟瀏览器 (Brave)
SC没有这个问题


现在是前发式注入,在所有网址都做注入,因此一定能跟注入的脚本对话
改成我上面提的后发式的话,我不知道会不会因此而有没运作的脚本 (要看UserScript API怎写。就是从navigation request, navigation start loading, navigation done, page loading, page done .... 是哪个时刻做注入)
因此也要保留SC现在的前发式。

当然,后发式的话,脚本不改,网址一致的话,下一次再载入一定能触发

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants