"""Runtime monkey patch that injects a Gradio background-scheduler fix into templates."""
from __future__ import annotations
import sys
from pathlib import Path
from typing import Callable
ENABLE_GRADIO_FOCUS_QUEUE_MONKEYPATCH = True
GRADIO_FOCUS_QUEUE_MONKEYPATCH_VERBOSE = False
_PATCH_SENTINEL = "window.__gradioFocusQueuePatch"
_TARGET_TEMPLATES = {"frontend/index.html", "frontend/share.html"}
_PROJECT_ROOT = Path(__file__).resolve().parents[2]
def get_javascript() -> str:
if not ENABLE_GRADIO_FOCUS_QUEUE_MONKEYPATCH:
return ""
verbose = "true" if GRADIO_FOCUS_QUEUE_MONKEYPATCH_VERBOSE else "false"
return f"""
(function () {{
if (typeof window === "undefined" || window.__gradioFocusQueuePatch) {{
return;
}}
const nativeRequestAnimationFrame = window.requestAnimationFrame.bind(window);
const nativeCancelAnimationFrame = window.cancelAnimationFrame.bind(window);
const channel = typeof MessageChannel === "function" ? new MessageChannel() : null;
function isElementVisible(element) {{
if (!element) {{
return false;
}}
const rect = element.getBoundingClientRect();
const style = window.getComputedStyle(element);
return style.display !== "none" && style.visibility !== "hidden" && rect.width > 0 && rect.height > 0;
}}
function getVideoGenTab() {{
return Array.from(document.querySelectorAll('[role="tab"]')).find((element) => element.textContent.trim() === "Video Generator") || null;
}}
function getVideoGenPanel() {{
const tab = getVideoGenTab();
const panelId = tab?.getAttribute("aria-controls");
const panel = panelId ? document.getElementById(panelId) : null;
return isElementVisible(panel) ? panel : null;
}}
function isVideoGenActive() {{
return getVideoGenPanel() !== null;
}}
const patch = {{
enabled: true,
forceBackground: false,
verbose: {verbose},
nextId: 1,
pending: new Map(),
queue: [],
nativeRequestAnimationFrame,
nativeCancelAnimationFrame,
isBackground() {{
if (this.forceBackground) {{
return true;
}}
try {{
return document.visibilityState !== "visible" || !document.hasFocus();
}} catch (_error) {{
return false;
}}
}},
shouldPatch() {{
return this.enabled && this.isBackground() && isVideoGenActive();
}},
shouldPatchAnimationFrame(stack, callback) {{
if (!this.shouldPatch()) {{
return false;
}}
const stackText = String(stack || "");
const source = String(callback || "");
const isBlocksDispatch = stackText.includes("/assets/Blocks-") && source.includes("Jt(");
const isCoreFlush = stackText.includes("/assets/index-") && source.includes("l.update(") && source.includes("ge.length") && source.includes("f.props[v.prop]=j");
return isBlocksDispatch || isCoreFlush;
}}
}};
function cancelSynthetic(id) {{
const job = patch.pending.get(id);
if (!job) {{
return false;
}}
job.canceled = true;
patch.pending.delete(id);
return true;
}}
function dispatchSynthetic(job) {{
if (!job || job.canceled) {{
return;
}}
patch.pending.delete(job.id);
try {{
if (job.kind === "raf") {{
job.callback(window.performance.now());
}}
}} catch (error) {{
window.setTimeout(() => {{
throw error;
}}, 0);
}}
}}
function flushOne() {{
const job = patch.queue.shift();
dispatchSynthetic(job);
}}
function scheduleSyntheticAnimationFrame(callback) {{
if (!channel) {{
return nativeRequestAnimationFrame(callback);
}}
const id = -patch.nextId++;
const job = {{ id, kind: "raf", callback, args: null, canceled: false }};
patch.pending.set(id, job);
patch.queue.push(job);
channel.port2.postMessage(id);
if (patch.verbose) {{
console.debug("[Gradio] focus queue synthetic animation frame", id);
}}
return id;
}}
if (channel) {{
channel.port1.onmessage = flushOne;
}}
window.__gradioFocusQueuePatch = patch;
window.requestAnimationFrame = function (callback) {{
if (typeof callback !== "function") {{
return nativeRequestAnimationFrame(callback);
}}
if (!patch.shouldPatch()) {{
return nativeRequestAnimationFrame(callback);
}}
const stack = new Error().stack || "";
if (!patch.shouldPatchAnimationFrame(stack, callback)) {{
return nativeRequestAnimationFrame(callback);
}}
return scheduleSyntheticAnimationFrame(callback);
}};
window.cancelAnimationFrame = function (id) {{
if (cancelSynthetic(id)) {{
return;
}}
return nativeCancelAnimationFrame(id);
}};
console.info("[Gradio] focus queue patch installed");
}})();
"""
def _inject_script(template_source: str) -> str:
if _PATCH_SENTINEL in template_source:
return template_source
script_tag = f"\n\t\t\n"
module_tag = '