@@ -8,13 +8,22 @@ import { ScriptService } from "./script";
88import { runScript , stopScript } from "../offscreen/client" ;
99import { getRunAt } from "./utils" ;
1010import { randomString } from "@App/pkg/utils/utils" ;
11- import { compileInjectScript , compileInjectScriptInfo , compileScriptCode } from "@App/runtime/content/utils" ;
11+ import { compileInjectScript , compileScriptCode } from "@App/runtime/content/utils" ;
1212import Cache from "@App/app/cache" ;
13- import { dealPatternMatches } from "@App/pkg/utils/match" ;
13+ import { dealPatternMatches , UrlMatch } from "@App/pkg/utils/match" ;
14+
15+ // 为了优化性能,存储到缓存时删除了code与value
16+ export interface ScriptMatchInfo extends ScriptRunResouce {
17+ matches : string [ ] ;
18+ excludeMatches : string [ ] ;
19+ }
1420
1521export class RuntimeService {
1622 scriptDAO : ScriptDAO = new ScriptDAO ( ) ;
1723
24+ scriptMatch : UrlMatch < string > = new UrlMatch < string > ( ) ;
25+ scriptMatchCache : Map < string , ScriptMatchInfo > | null | undefined ;
26+
1827 constructor (
1928 private group : Group ,
2029 private sender : MessageSend ,
@@ -99,12 +108,23 @@ export class RuntimeService {
99108 }
100109
101110 async pageLoad ( _ , sender : GetSender ) {
102- const scriptFlag = await this . messageFlag ( ) ;
111+ const [ scriptFlag , match ] = await Promise . all ( [ this . messageFlag ( ) , this . loadScriptMatchInfo ( ) ] ) ;
103112 const chromeSender = sender . getSender ( ) as chrome . runtime . MessageSender ;
104- // 匹配当前页面的脚本
105- console . log ( "pageLoad" ) ;
106113
107- return Promise . resolve ( { flag : scriptFlag } ) ;
114+ // 匹配当前页面的脚本
115+ const matchScriptUuid = match . match ( chromeSender . url ! ) ;
116+ console . log ( "pageLoad" , match . match ( chromeSender . url ! ) ) ;
117+ const scripts = await Promise . all (
118+ matchScriptUuid . map (
119+ ( uuid ) =>
120+ new Promise ( ( resolve ) => {
121+ // 获取value
122+ const scriptRes = Object . assign ( { } , this . scriptMatchCache ?. get ( uuid ) ) ;
123+ resolve ( scriptRes ) ;
124+ } )
125+ )
126+ ) ;
127+ return Promise . resolve ( { flag : scriptFlag , scripts : scripts } ) ;
108128 }
109129
110130 // 停止脚本
@@ -155,6 +175,70 @@ export class RuntimeService {
155175 } ) ;
156176 }
157177
178+ loadScripting : Promise < void > | null | undefined ;
179+
180+ // 加载脚本匹配信息,由于service_worker的机制,如果由不活动状态恢复过来时,会优先触发事件
181+ // 可能当时会没有脚本匹配信息,所以使用脚本信息时,尽量使用此方法获取
182+ async loadScriptMatchInfo ( ) {
183+ if ( this . scriptMatchCache ) {
184+ return this . scriptMatch ;
185+ }
186+ if ( this . loadScripting ) {
187+ await this . loadScripting ;
188+ } else {
189+ // 如果没有缓存, 则创建一个新的缓存
190+ this . loadScripting = Cache . getInstance ( )
191+ . get ( "scriptMatch" )
192+ . then ( ( data : { [ key : string ] : ScriptMatchInfo } ) => {
193+ this . scriptMatchCache = new Map < string , ScriptMatchInfo > ( ) ;
194+ if ( data ) {
195+ Object . keys ( data ) . forEach ( ( key ) => {
196+ const item = data [ key ] ;
197+ this . scriptMatchCache ! . set ( item . uuid , item ) ;
198+ item . matches . forEach ( ( match ) => {
199+ this . scriptMatch . add ( match , item . uuid ) ;
200+ } ) ;
201+ item . excludeMatches . forEach ( ( match ) => {
202+ this . scriptMatch . exclude ( match , item . uuid ) ;
203+ } ) ;
204+ } ) ;
205+ }
206+ } ) ;
207+ await this . loadScripting ;
208+ this . loadScripting = null ;
209+ }
210+ return this . scriptMatch ;
211+ }
212+
213+ // 保存脚本匹配信息
214+ async saveScriptMatchInfo ( ) {
215+ if ( ! this . scriptMatchCache ) {
216+ return ;
217+ }
218+ const scriptMatch = { } as { [ key : string ] : ScriptMatchInfo } ;
219+ this . scriptMatchCache . forEach ( ( val , key ) => {
220+ scriptMatch [ key ] = val ;
221+ // 优化性能,将不需要的信息去掉
222+ scriptMatch [ key ] . code = "" ;
223+ scriptMatch [ key ] . value = { } ;
224+ } ) ;
225+ return await Cache . getInstance ( ) . set ( "scriptMatch" , scriptMatch ) ;
226+ }
227+
228+ async addScriptMatch ( item : ScriptMatchInfo ) {
229+ if ( ! this . scriptMatchCache ) {
230+ await this . loadScriptMatchInfo ( ) ;
231+ }
232+ this . scriptMatchCache ! . set ( item . uuid , item ) ;
233+ item . matches . forEach ( ( match ) => {
234+ this . scriptMatch . add ( match , item . uuid ) ;
235+ } ) ;
236+ item . excludeMatches . forEach ( ( match ) => {
237+ this . scriptMatch . exclude ( match , item . uuid ) ;
238+ } ) ;
239+ this . saveScriptMatchInfo ( ) ;
240+ }
241+
158242 async registryPageScript ( script : Script ) {
159243 if ( await Cache . getInstance ( ) . has ( "registryScript:" + script . uuid ) ) {
160244 return ;
@@ -170,6 +254,11 @@ export class RuntimeService {
170254
171255 matches . push ( ...( script . metadata [ "include" ] || [ ] ) ) ;
172256 const patternMatches = dealPatternMatches ( matches ) ;
257+ const scriptMatchInfo : ScriptMatchInfo = Object . assign (
258+ { matches : patternMatches . result , excludeMatches : [ ] } ,
259+ scriptRes
260+ ) ;
261+
173262 const registerScript : chrome . userScripts . RegisteredUserScript = {
174263 id : scriptRes . uuid ,
175264 js : [ { code : scriptRes . code } ] ,
@@ -186,13 +275,16 @@ export class RuntimeService {
186275 const result = dealPatternMatches ( excludeMatches ) ;
187276
188277 registerScript . excludeMatches = result . patternResult ;
278+ scriptMatchInfo . excludeMatches = result . result ;
189279 }
190280 if ( script . metadata [ "run-at" ] ) {
191281 registerScript . runAt = getRunAt ( script . metadata [ "run-at" ] ) ;
192282 }
193- chrome . userScripts . register ( [ registerScript ] , ( ) => {
283+ chrome . userScripts . register ( [ registerScript ] , async ( ) => {
194284 // 标记为已注册
195285 Cache . getInstance ( ) . set ( "registryScript:" + script . uuid , true ) ;
286+ // 将脚本match信息放入缓存中
287+ this . addScriptMatch ( scriptMatchInfo ) ;
196288 } ) ;
197289 }
198290
0 commit comments