@@ -18600,6 +18600,136 @@ if (typeof self !== 'undefined') {
1860018600 self.GMNotificationHandler = GMNotificationHandler;
1860118601}
1860218602
18603+ // ============================================================================
18604+ // Generated from src/background/gm-resource-handler.ts; do not edit by hand.
18605+ // Run `node scripts/generate-ts-runtime-modules.mjs` or `npm run build:bg`.
18606+ // ============================================================================
18607+
18608+ const GMResourceHandler = (() => {
18609+ const module = { exports: {} };
18610+ const exports = module.exports;
18611+ "use strict";
18612+ var __defProp = Object.defineProperty;
18613+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
18614+ var __getOwnPropNames = Object.getOwnPropertyNames;
18615+ var __hasOwnProp = Object.prototype.hasOwnProperty;
18616+ var __export = (target, all) => {
18617+ for (var name in all)
18618+ __defProp(target, name, { get: all[name], enumerable: true });
18619+ };
18620+ var __copyProps = (to, from, except, desc) => {
18621+ if (from && typeof from === "object" || typeof from === "function") {
18622+ for (let key of __getOwnPropNames(from))
18623+ if (!__hasOwnProp.call(to, key) && key !== except)
18624+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18625+ }
18626+ return to;
18627+ };
18628+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18629+
18630+ // src/background/gm-resource-handler.ts
18631+ var gm_resource_handler_exports = {};
18632+ __export(gm_resource_handler_exports, {
18633+ GMResourceHandler: () => GMResourceHandler,
18634+ GM_RESOURCE_ACTIONS: () => GM_RESOURCE_ACTIONS,
18635+ default: () => gm_resource_handler_default,
18636+ handleGMResourceMessage: () => handleGMResourceMessage,
18637+ isGMResourceAction: () => isGMResourceAction
18638+ });
18639+ module.exports = __toCommonJS(gm_resource_handler_exports);
18640+ var GM_RESOURCE_ACTIONS = [
18641+ "GM_getResourceText",
18642+ "GM_getResourceURL",
18643+ "GM_loadScript"
18644+ ];
18645+ var GM_RESOURCE_ACTION_SET = new Set(GM_RESOURCE_ACTIONS);
18646+ function errorMessage(error, fallback) {
18647+ if (error && typeof error === "object" && "message" in error) {
18648+ const message = error.message;
18649+ if (typeof message === "string" && message) return message;
18650+ }
18651+ return fallback;
18652+ }
18653+ function isGMResourceAction(action) {
18654+ return typeof action === "string" && GM_RESOURCE_ACTION_SET.has(action);
18655+ }
18656+ async function handleGMResourceMessage(action, data = {}) {
18657+ switch (action) {
18658+ case "GM_getResourceText": {
18659+ const script = await ScriptStorage.get(data.scriptId);
18660+ if (!script || !script.meta?.resource) return null;
18661+ const url = data.name ? script.meta.resource[data.name] : void 0;
18662+ if (!url) return null;
18663+ try {
18664+ return await ResourceCache.fetchResource(url);
18665+ } catch (_) {
18666+ return null;
18667+ }
18668+ }
18669+ case "GM_getResourceURL": {
18670+ const script = await ScriptStorage.get(data.scriptId);
18671+ if (!script || !script.meta?.resource) return null;
18672+ const url = data.name ? script.meta.resource[data.name] : void 0;
18673+ if (!url) return null;
18674+ try {
18675+ return await ResourceCache.getDataUri(url);
18676+ } catch (_) {
18677+ return null;
18678+ }
18679+ }
18680+ case "GM_loadScript": {
18681+ try {
18682+ if (!data.url) return { error: "No URL provided" };
18683+ if (!data.scriptId) return { error: "Missing script context" };
18684+ const script = await ScriptStorage.get(data.scriptId);
18685+ if (!script) return { error: "Script context not found" };
18686+ const policy = evaluateConnectPolicy(script, data.url);
18687+ if (!policy.allowed) return { error: policy.error };
18688+ const preCheck = InternalHostGuard.classifyFetchUrl(data.url, ["http:", "https:"]);
18689+ if (!preCheck.ok) {
18690+ return { error: "GM_loadScript URL rejected: " + preCheck.message };
18691+ }
18692+ const controller = new AbortController();
18693+ const timeoutId = setTimeout(() => controller.abort(), data.timeout || 3e4);
18694+ let code;
18695+ try {
18696+ const response = await fetch(data.url, { signal: controller.signal });
18697+ if (!response.ok) return { error: `HTTP ${response.status}` };
18698+ const postCheck = InternalHostGuard.classifyResponseUrl(response, ["http:", "https:"]);
18699+ if (!postCheck.ok) {
18700+ return { error: "GM_loadScript URL redirected to " + postCheck.message };
18701+ }
18702+ try {
18703+ code = await _fetchTextBounded(response, MAX_SCRIPT_SIZE, "Script");
18704+ } catch (sizeError) {
18705+ return { error: errorMessage(sizeError, String(sizeError)) };
18706+ }
18707+ } finally {
18708+ clearTimeout(timeoutId);
18709+ }
18710+ if (!code || code.length === 0) return { error: "Empty response" };
18711+ return { code };
18712+ } catch (error) {
18713+ return { error: errorMessage(error, "Fetch failed") };
18714+ }
18715+ }
18716+ default:
18717+ return { error: `Unsupported GM resource action: ${action}` };
18718+ }
18719+ }
18720+ var GMResourceHandler = Object.freeze({
18721+ GM_RESOURCE_ACTIONS,
18722+ handleGMResourceMessage,
18723+ isGMResourceAction
18724+ });
18725+ var gm_resource_handler_default = GMResourceHandler;
18726+ return module.exports.default || module.exports.GMResourceHandler || module.exports;
18727+ })();
18728+
18729+ if (typeof self !== 'undefined') {
18730+ self.GMResourceHandler = GMResourceHandler;
18731+ }
18732+
1860318733// ============================================================================
1860418734// Generated from src/background/connect-policy.ts; do not edit by hand.
1860518735// Run `node scripts/generate-ts-runtime-modules.mjs` or `npm run build:bg`.
@@ -37270,76 +37400,12 @@ async function handleMessage(message, sender) {
3727037400 case 'fetchResource':
3727137401 return await ResourceCache.fetchResource(data.url);
3727237402
37273- case 'GM_getResourceText': {
37274- const script = await ScriptStorage.get(data.scriptId);
37275- if (!script || !script.meta.resource) return null;
37276- const url = script.meta.resource[data.name];
37277- if (!url) return null;
37278- try {
37279- return await ResourceCache.fetchResource(url);
37280- } catch (e) {
37281- return null;
37282- }
37283- }
37284-
37285- case 'GM_getResourceURL': {
37286- const script2 = await ScriptStorage.get(data.scriptId);
37287- if (!script2 || !script2.meta.resource) return null;
37288- const url2 = script2.meta.resource[data.name];
37289- if (!url2) return null;
37290- try {
37291- return await ResourceCache.getDataUri(url2);
37292- } catch (e) {
37293- return null;
37294- }
37295- }
37296-
37297- // GM_loadScript - Fetch a script URL and return its source code
37298- // Allows userscripts to dynamically load libraries at runtime
37299- case 'GM_loadScript': {
37300- try {
37301- if (!data.url) return { error: 'No URL provided' };
37302- if (!data.scriptId) return { error: 'Missing script context' };
37303- const lsScript = await ScriptStorage.get(data.scriptId);
37304- if (!lsScript) return { error: 'Script context not found' };
37305-
37306- // Enforce @connect for GM_loadScript (same rules as GM_xmlhttpRequest)
37307- const lsPolicy = evaluateConnectPolicy(lsScript, data.url);
37308- if (!lsPolicy.allowed) {
37309- return { error: lsPolicy.error };
37310- }
37311- const lsPreCheck = InternalHostGuard.classifyFetchUrl(data.url, ['http:', 'https:']);
37312- if (!lsPreCheck.ok) {
37313- return { error: 'GM_loadScript URL rejected: ' + lsPreCheck.message };
37314- }
37315-
37316- const controller = new AbortController();
37317- const timeoutId = setTimeout(() => controller.abort(), data.timeout || 30000);
37318- let code;
37319- try {
37320- const response = await fetch(data.url, { signal: controller.signal });
37321- if (!response.ok) return { error: `HTTP ${response.status}` };
37322- const lsPostCheck = InternalHostGuard.classifyResponseUrl(response, ['http:', 'https:']);
37323- if (!lsPostCheck.ok) {
37324- return { error: 'GM_loadScript URL redirected to ' + lsPostCheck.message };
37325- }
37326- // Stream-bounded read so a remote script source can't OOM us
37327- // by serving an unbounded body. See _fetchTextBounded for
37328- // rationale.
37329- try {
37330- code = await _fetchTextBounded(response, MAX_SCRIPT_SIZE, 'Script');
37331- } catch (sizeErr) {
37332- return { error: sizeErr?.message || String(sizeErr) };
37333- }
37334- } finally {
37335- clearTimeout(timeoutId);
37336- }
37337- if (!code || code.length === 0) return { error: 'Empty response' };
37338- return { code };
37339- } catch (e) {
37340- return { error: e?.message || 'Fetch failed' };
37341- }
37342- }
37403+ // GM resources and GM_loadScript dynamic library loading
37404+ case 'GM_getResourceText':
37405+ case 'GM_getResourceURL':
37406+ case 'GM_loadScript':
37407+ if (typeof GMResourceHandler === 'undefined') return { error: 'GMResourceHandler not available' };
37408+ return await GMResourceHandler.handleGMResourceMessage(action, data);
3734337409
3734437410 // XHR - Using fetch() since XMLHttpRequest is not available in Service Workers
3734537411 // Provides abort support via AbortController and simulates events
0 commit comments