(monkey)
| 127 | |
| 128 | /* ================== 拼接最终代码 ================== */ |
| 129 | const buildFinalCode = (monkey) => { |
| 130 | let requires = (monkey.mRequireJs || '').split(/[\s,,]+/).map(s => s.trim()).filter(Boolean); |
| 131 | let userScript = monkey.mScript || ''; |
| 132 | let refresh = parseInt(monkey.mRefresh) || 0; |
| 133 | let nameStr = JSON.stringify(monkey.mName || ''); |
| 134 | let idStr = JSON.stringify(monkey.id); |
| 135 | |
| 136 | // 注意:MAIN world 没有 chrome.runtime API,所以日志一律走 |
| 137 | // window.postMessage('FH_MONKEY_LOG' channel),由 ISOLATED world |
| 138 | // 桥接器(_injectLogBridge)转发到 background。 |
| 139 | return ` |
| 140 | (function(){ |
| 141 | ${buildGmApi(monkey)} |
| 142 | |
| 143 | var __post = function(level, msg){ |
| 144 | try { |
| 145 | window.postMessage({ |
| 146 | __fh_monkey_log: true, |
| 147 | payload: { |
| 148 | id: ${idStr}, |
| 149 | name: ${nameStr}, |
| 150 | level: level, |
| 151 | msg: String((msg && msg.stack) || msg), |
| 152 | url: location.href, |
| 153 | time: Date.now() |
| 154 | } |
| 155 | }, '*'); |
| 156 | } catch(_) {} |
| 157 | }; |
| 158 | var __reportError = function(e){ |
| 159 | __post('error', e); |
| 160 | try { console.error('[FH-Monkey:' + ${nameStr} + ']', e); } catch(_) {} |
| 161 | }; |
| 162 | |
| 163 | // 让 GM_log 也回流到运行日志面板(每个脚本作用域独立闭包,必须每次都 hook) |
| 164 | try { |
| 165 | if (typeof GM_log === 'function') { |
| 166 | var __origGmLog = GM_log; |
| 167 | GM_log = function(){ |
| 168 | try { |
| 169 | var args = [].slice.call(arguments); |
| 170 | var text = args.map(function(a){ |
| 171 | try { return typeof a === 'object' ? JSON.stringify(a) : String(a); } catch(_) { return String(a); } |
| 172 | }).join(' '); |
| 173 | __post('info', text); |
| 174 | } catch(_) {} |
| 175 | try { return __origGmLog.apply(null, arguments); } catch(_) {} |
| 176 | }; |
| 177 | } |
| 178 | } catch(_) {} |
| 179 | |
| 180 | // 全局 console / error / unhandledrejection 监听只挂一次(避免多脚本 N 倍重复 + 归属错乱), |
| 181 | // 由全局 sentinel 控制;归属为通用 'page-monkey',具体脚本错误请用 try-catch 自行 GM_log。 |
| 182 | try { |
| 183 | if (!window.__fhMonkeyGlobalHooked) { |
| 184 | window.__fhMonkeyGlobalHooked = true; |
| 185 | var __postGlobal = function(level, msg){ |
| 186 | try { |
no test coverage detected