Files
Nitro-V3/src/pixiPatch.ts
T
2026-06-06 08:42:18 +02:00

81 lines
2.1 KiB
TypeScript

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<string, unknown>).DefaultBatcher ],
[ 'Batcher', (PIXI as Record<string, unknown>).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();