Set crossOrigin = "anonymous" on canvas-bound icon images (#3789)

## Description:

StructureLayer.loadIcon and StructureDrawingUtils.loadIcon hand-roll new
Image() and feed the result into a canvas. With assets now served from a
cross-origin CDN, the default no-cors fetch tainted the canvas, and
WebGL's texImage2D rejected the upload `Uncaught SecurityError: Tainted
canvases may not be loaded`. Setting crossOrigin = "anonymous" before
src switches to a CORS-checked fetch (R2 already returns ACAO), so the
canvas stays clean and the texture upload succeeds.

Other new Image() and <img> sites in the codebase don't need the change
— they're either DOM-only or read naturalWidth/naturalHeight only.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
This commit is contained in:
Evan
2026-04-28 09:53:22 -06:00
committed by GitHub
parent fc45410ee5
commit 01b3cbe332
2 changed files with 8 additions and 0 deletions
@@ -89,6 +89,10 @@ export class SpriteFactory {
unitType: UnitType,
) {
const image = new Image();
// crossOrigin must be set before src so the fetch is CORS-checked.
// Without this, an icon served from CDN_BASE taints structureCanvas
// and PIXI.Texture.from rejects the upload to WebGL.
image.crossOrigin = "anonymous";
image.src = unitInfo.iconPath;
image.onload = () => {
unitInfo.image = image;
@@ -87,6 +87,10 @@ export class StructureLayer implements Layer {
private loadIcon(unitType: string, config: UnitRenderConfig) {
const image = new Image();
// crossOrigin must be set before src so the fetch is CORS-checked.
// Without this, an icon served from CDN_BASE taints any canvas/texture
// it's drawn into, and WebGL refuses to upload it via texImage2D.
image.crossOrigin = "anonymous";
image.src = config.icon;
image.onload = () => {
this.unitIcons.set(unitType, image);