Critical security fixes ----------------------- - Sandbox Jinja2 in template_render + prompt_template_render (was RCE via shared workflows) - Drop user home dir from filesystem allow-list (was arbitrary delete/overwrite) - Confine save_image_with_manifest + sanitize filename basename - SSRF block on http_get/http_post/notify_webhook (catches 169.254.169.254 metadata) - Case-insensitive path confinement on Windows Critical correctness/perf ------------------------- - halftone_dots: O(N^2) -> O(cells*36); was freezing worker on 1024+ images - Preserve latent dict keys (noise_mask, batch_index) in latent_math/noise/upscale - Preserve alpha channel in invert + threshold_binary on RGBA inputs - Force odd kernel in mask_erode/mask_dilate to prevent H+1 shape mismatch - Snap aspect_ratio_pick output to multiples of 8 (was crashing SD UNet) Theme engine (JS) ----------------- - Hoist window.matchMedia() out of per-frame hot path -> recovers 200 FPS from 25 - Wrap-once draw method to stop stomping other extensions wrappers - nodeRemoved hook + WeakMap groups + in-place canvas reuse -> three memory leaks closed - Wire thickness now uses connections_width (the wrap was a no-op vs LiteGraph) - onGroupAdded auto-themes new groups; budget change triggers redraw - Gradient caching in synthwave/glassmorphic New ops (10) ------------ - json_path (programming): dotted/bracketed path extract - latent_nan_guard, latent_pad_crop (mask_latent) - mask_from_depth, mask_invert (mask_latent) - color_match_histogram, image_composite_over (image_pro/value) - frequency_separation (image_pro/style) - pad_to_multiple (image_pro/spatial) - save_images_zip (io_workflow) - llm_enhance_prompt via Ollama / LM Studio / llama.cpp (prompt) Theme UX -------- - Right-click "Theme..." submenu on every node (including vanilla ComfyUI nodes) - Auto-contrast title text (WCAG AA-based flip) Tests: 373 Python + 33 JS = 406 passing (added 33 new tests for security + features). Full review notes in CHANGELOG.md.
26 lines
1.1 KiB
JavaScript
26 lines
1.1 KiB
JavaScript
export function createThemeApi({ settings, getVisibleThemedCount }) {
|
|
// Evaluate prefers-reduced-motion ONCE at construction. Calling
|
|
// window.matchMedia() inside the hot path was allocating a new
|
|
// MediaQueryList per themed-node per frame (≈20k allocs/sec at 200Hz
|
|
// with globalOverrideEnabled), which collapsed the canvas to ~25 FPS.
|
|
// We listen for OS-level changes asynchronously instead.
|
|
let prefersReducedMotion = false;
|
|
if (typeof window !== "undefined" && window.matchMedia) {
|
|
const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
prefersReducedMotion = mq.matches;
|
|
const onChange = (e) => { prefersReducedMotion = e.matches; };
|
|
if (mq.addEventListener) mq.addEventListener("change", onChange);
|
|
else if (mq.addListener) mq.addListener(onChange); // legacy Safari
|
|
}
|
|
|
|
return {
|
|
motionAllowed(level) {
|
|
if (level === "none") return false;
|
|
if (settings.reduceMotion) return false;
|
|
if (prefersReducedMotion) return false;
|
|
if (getVisibleThemedCount() > settings.heavyThemeNodeBudget) return false;
|
|
return true;
|
|
},
|
|
};
|
|
}
|