docs(shader-transitions): clarify allowTaint caveat in capture comment

Address Copilot review comment on #456: the old `allowTaint` doc comment
said the resulting canvas is "still usable as a WebGL texture via
gl.texImage2D (no pixel read-back required)", which is wrong. A tainted
canvas CANNOT be uploaded to WebGL — the spec requires SecurityError on
non-origin-clean sources with no opt-out. That's exactly what we observe
in Safari + SVG-filter compositions, and what hyper-shader.ts's catch
handler now handles via CSS crossfade.

Update the comment to correctly describe the flag's effect: it only
moves the failure point from html2canvas to texImage2D; the end-user
UX is the same (smooth CSS fade in either case). The flag remains
defensively correct for the non-taint branches where it genuinely
helps (cross-origin images with `Access-Control-Allow-Origin`).

No code change — comment only.

Made-with: Cursor
This commit is contained in:
ukimsanov
2026-04-23 16:20:32 -04:00
parent b3b458fda4
commit 41b4017273
+20 -7
View File
@@ -37,14 +37,27 @@ export function captureScene(sceneEl: HTMLElement, bgColor: string): Promise<HTM
// with <filter> elements (e.g. feTurbulence grain backgrounds), certain
// cross-origin images, and mask/clip-path url() refs can taint the
// output canvas on WebKit. Without these flags, html2canvas throws
// `SecurityError: The operation is insecure` on read-back and every
// shader transition falls through to the hard-cut catch handler
// observed in Safari + Claude Design's cross-origin iframe sandbox.
// `SecurityError: The operation is insecure` during its own read-back
// path and every shader transition falls through to the catch handler
// observed in Safari + Claude Design's cross-origin iframe sandbox.
//
// useCORS: send CORS headers on same-/cross-origin image fetches.
// allowTaint: proceed even when canvas becomes tainted; the resulting
// canvas is still usable as a WebGL texture via
// gl.texImage2D (no pixel read-back required).
// useCORS: send CORS headers on image fetches so cross-origin images
// with proper `Access-Control-Allow-Origin` don't taint the
// canvas in the first place. Strict improvement.
// allowTaint: let html2canvas complete and return a canvas even when it
// becomes tainted (instead of throwing). Important caveat:
// a tainted canvas CANNOT be uploaded to WebGL via
// `gl.texImage2D` — WebGL spec requires SecurityError on
// non-origin-clean sources, with no opt-out. So this flag
// only moves the failure point from html2canvas to the
// texImage2D call in webgl.ts. In both cases `hyper-shader.ts`
// catches the rejected promise and runs the CSS crossfade
// fallback. Net effect: the end-user UX is the same (smooth
// CSS fade in either case), but we get a cleaner, more
// predictable error site and the flag is defensively
// correct for the non-taint branches where it genuinely
// helps (e.g., `crossOrigin="anonymous"` image fetches
// that already had CORS headers).
useCORS: true,
allowTaint: true,
ignoreElements: (el: Element) => el.tagName === "CANVAS" || el.hasAttribute("data-no-capture"),