import * as PIXI from 'pixi.js'; type AnyFn = (...args: unknown[]) => unknown; interface MethodHost { [key: string]: unknown; } declare global { interface Window { __nitroPixiBatcherPatched__?: boolean; } } const NULL_TEXTURE_MARKERS = /alphaMode|reading 'uid'|reading 'destroyed'|reading 'source'/; const isNullTextureCrash = (err: unknown): boolean => { if(!(err instanceof TypeError)) return false; return NULL_TEXTURE_MARKERS.test(err.message ?? ''); }; const guardMethod = (proto: MethodHost, methodName: string, label: string): boolean => { const original = proto[methodName]; if(typeof original !== 'function') return false; if((original as { __nitroGuarded__?: boolean }).__nitroGuarded__) return false; const guarded = function(this: unknown, ...args: unknown[]) { try { return (original as AnyFn).apply(this, args); } catch(err) { if(isNullTextureCrash(err)) return undefined; throw err; } }; (guarded as { __nitroGuarded__?: boolean }).__nitroGuarded__ = true; proto[methodName] = guarded; console.info(`[NitroPixiPatch] guarded ${ label }.prototype.${ methodName } against null textureSource`); return true; }; const installPatch = (): void => { if(typeof window === 'undefined') return; if(window.__nitroPixiBatcherPatched__) return; const candidates: Array<[string, unknown]> = [ [ 'DefaultBatcher', (PIXI as Record).DefaultBatcher ], [ 'Batcher', (PIXI as Record).Batcher ] ]; let patched = false; for(const [ name, ctor ] of candidates) { const proto = (ctor as { prototype?: MethodHost } | undefined)?.prototype; if(!proto) continue; if(guardMethod(proto, 'break', name)) patched = true; if(guardMethod(proto, 'checkAndUpdateTexture', name)) patched = true; } window.__nitroPixiBatcherPatched__ = patched; if(!patched) { console.warn('[NitroPixiPatch] could not locate Batcher.prototype methods - is pixi.js export shape unchanged?'); } }; installPatch();