fix(nitro): repair stale meta.image in bundles that are already lossless
A bundle whose texture is already VP8L was returned untouched, so a stale spritesheet.meta.image survived the normalisation and the client could not find the texture member. Rebuild the archive in that case and reuse the existing VP8L bytes instead of decoding them again.
This commit is contained in:
1 parent
9ee22db8ba
commit
d176fad4da
2 files changed
+33
-2
No files matched your search
@@ -520,14 +520,29 @@ function inflateJsonOrGzip(
|
||||
* renamed. `meta.image` is corrected by `createNitroBundle`.
|
||||
*
|
||||
* A bundle that is already lossless WebP is returned untouched, which keeps
|
||||
* the operation idempotent and avoids a pointless re-encode.
|
||||
* the operation idempotent and avoids a pointless re-encode — but only when
|
||||
* its metadata is already consistent. A bundle whose `meta.image` names a
|
||||
* member that is not in the file is still rebuilt, because a client that
|
||||
* cannot find the texture renders nothing and a re-encode is not what fixes
|
||||
* that.
|
||||
*
|
||||
* Throws if the texture claims to be PNG or WebP but cannot actually be
|
||||
* decoded; callers that would rather keep the original should catch.
|
||||
*/
|
||||
export async function toWebpLosslessBundle(bundle: Buffer): Promise<Buffer> {
|
||||
const parsed = parseNitroBundle(bundle);
|
||||
if (isLosslessWebp(parsed.texture)) return bundle;
|
||||
const meta = (parsed.json as { spritesheet?: { meta?: { image?: string } } })
|
||||
.spritesheet?.meta;
|
||||
if (isLosslessWebp(parsed.texture)) {
|
||||
if (meta?.image === parsed.textureFileName) return bundle;
|
||||
// Stale metadata only: rebuild the archive with the pointer corrected
|
||||
// and reuse the existing VP8L bytes rather than re-encoding them.
|
||||
return createNitroBundle(
|
||||
parsed.json,
|
||||
parsed.texture,
|
||||
parsed.textureFileName.replace(/\.(?:png|webp)$/i, ""),
|
||||
);
|
||||
}
|
||||
|
||||
const image = sharp(parsed.texture);
|
||||
const { width = 0, height = 0 } = await image.metadata();
|
||||
|
||||
@@ -223,6 +223,22 @@ describe("normalising a bundle to WebP Lossless", () => {
|
||||
);
|
||||
await expect(toWebpLosslessBundle(broken)).rejects.toThrow();
|
||||
});
|
||||
|
||||
it("repairs stale meta.image in a bundle that is already lossless", async () => {
|
||||
// Already VP8L, so there is nothing to re-encode — but the pointer
|
||||
// names a member the archive does not contain, which a re-encode
|
||||
// would not be what fixes.
|
||||
const stale = await bundleWith("webp", "chair.png");
|
||||
expect(isLosslessWebp(parseNitroBundle(stale).texture)).toBe(true);
|
||||
|
||||
const after = parseNitroBundle(await toWebpLosslessBundle(stale));
|
||||
expect(after.textureFileName).toBe("chair.webp");
|
||||
expect(
|
||||
(after.json.spritesheet as { meta: { image: string } }).meta.image,
|
||||
).toBe("chair.webp");
|
||||
// The existing VP8L bytes are reused rather than decoded again.
|
||||
expect(after.texture.equals(parseNitroBundle(stale).texture)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("spritesheet encoding", () => {
|
||||
|
||||
Reference in new issue
Block a user