@@ -1192,3 +1192,83 @@ describe("MQ 事件处理效果(enableScripts / deleteScripts / sortedScripts
11921192 expect ( ( runtime as any ) . cachedPatterns . has ( uuid ) ) . toBe ( false ) ;
11931193 } ) ;
11941194} ) ;
1195+
1196+ // ─────────────────────────────────────────────────────────────────────────────
1197+
1198+ describe ( "restoreJSCodeFromCompiledResource 还原代码时的生效 metadata" , ( ) => {
1199+ // 设置面板改运行时机只写 selfMetadata,脚本自带 metadata 原封不动;
1200+ // 还原路径若只看自带 metadata,重新注册后用户覆写就会静默失效(#1649)。
1201+ const createContext = ( script : Script ) => {
1202+ const { runtime, mockScriptService } = _createRuntimeContext ( ) ;
1203+ const scriptRes = _createScriptRunResource ( script ) ;
1204+ const compiledResource : CompiledResource = {
1205+ name : script . name ,
1206+ flag : `#-${ script . uuid } ` ,
1207+ uuid : script . uuid ,
1208+ require : [ ] ,
1209+ matches : [ "https://www.example.com/*" ] ,
1210+ includeGlobs : [ ] ,
1211+ excludeMatches : [ ] ,
1212+ excludeGlobs : [ ] ,
1213+ allFrames : false ,
1214+ world : "MAIN" ,
1215+ runAt : "document_idle" ,
1216+ scriptUrlPatterns : scriptURLPatternResults ( scriptRes ) ! . scriptUrlPatterns ,
1217+ originalUrlPatterns : null ,
1218+ } ;
1219+ mockScriptService . buildScriptRunResource . mockResolvedValue ( scriptRes ) ;
1220+ ( runtime as any ) . script = {
1221+ ...mockScriptService ,
1222+ scriptCodeDAO : { get : vi . fn ( ) . mockResolvedValue ( { code : "console.log(1);" } ) } ,
1223+ } ;
1224+ ( runtime as any ) . resource = { resourceDAO : { get : vi . fn ( ) . mockResolvedValue ( undefined ) } } ;
1225+ return { runtime, compiledResource } ;
1226+ } ;
1227+
1228+ it ( "selfMetadata 覆写 run-at=context-menu 时,还原的代码应包裹 GM_registerMenuCommand" , async ( ) => {
1229+ const script = _createMockScript ( {
1230+ metadata : { match : [ "https://www.example.com/*" ] , "run-at" : [ "document-idle" ] } ,
1231+ selfMetadata : { "run-at" : [ "context-menu" ] } ,
1232+ } ) ;
1233+ const { runtime, compiledResource } = createContext ( script ) ;
1234+
1235+ const code = await runtime . restoreJSCodeFromCompiledResource ( script , compiledResource ) ;
1236+
1237+ expect ( code ) . toContain ( "GM_registerMenuCommand" ) ;
1238+ } ) ;
1239+
1240+ it ( "selfMetadata 覆写为 early-start 时,还原的代码应走预注入编译" , async ( ) => {
1241+ const script = _createMockScript ( {
1242+ metadata : { match : [ "https://www.example.com/*" ] , "run-at" : [ "document-idle" ] } ,
1243+ selfMetadata : { "early-start" : [ "" ] , "run-at" : [ "document-start" ] } ,
1244+ } ) ;
1245+ const { runtime, compiledResource } = createContext ( script ) ;
1246+
1247+ const code = await runtime . restoreJSCodeFromCompiledResource ( script , compiledResource ) ;
1248+
1249+ expect ( code ) . toContain ( "performance.dispatchEvent" ) ;
1250+ } ) ;
1251+ } ) ;
1252+
1253+ describe ( "pushValueUpdate 判断是否需要为 early-start 脚本重新编译" , ( ) => {
1254+ // early-start 会把 GM 值编进预注入代码,值变了必须重编;
1255+ // 该脚本的 early-start 可能来自用户覆写,不能只看脚本自带 metadata。
1256+ it ( "selfMetadata 覆写为 early-start 的脚本,值更新后应重新编译注册" , async ( ) => {
1257+ const { runtime } = _createRuntimeContext ( ) ;
1258+ const script = _createMockScript ( {
1259+ metadata : { match : [ "https://www.example.com/*" ] , "run-at" : [ "document-idle" ] } ,
1260+ selfMetadata : { "early-start" : [ "" ] , "run-at" : [ "document-start" ] } ,
1261+ } ) ;
1262+ const updateSpy = vi . spyOn ( runtime , "updateResourceOnScriptChange" ) . mockResolvedValue ( undefined ) ;
1263+
1264+ await runtime . pushValueUpdate ( script , {
1265+ entries : [ ] ,
1266+ uuid : script . uuid ,
1267+ storageName : "test-storage" ,
1268+ sender : { runFlag : "" , tabId : - 1 } ,
1269+ valueUpdated : true ,
1270+ } ) ;
1271+
1272+ expect ( updateSpy ) . toHaveBeenCalledWith ( script ) ;
1273+ } ) ;
1274+ } ) ;
0 commit comments