fix(image-pipeline): skip pre-aborted source bitmap loads
This commit is contained in:
@@ -90,6 +90,8 @@ export async function loadSourceBitmap(
|
|||||||
throw new Error("ImageBitmap is not available in this environment.");
|
throw new Error("ImageBitmap is not available in this environment.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throwIfAborted(options.signal);
|
||||||
|
|
||||||
const promise = getOrCreateSourceBitmapPromise(sourceUrl);
|
const promise = getOrCreateSourceBitmapPromise(sourceUrl);
|
||||||
return await awaitWithLocalAbort(promise, options.signal);
|
return await awaitWithLocalAbort(promise, options.signal);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,36 @@ describe("loadSourceBitmap", () => {
|
|||||||
expect(createImageBitmap).toHaveBeenCalledTimes(1);
|
expect(createImageBitmap).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not start fetch/decode work or cache when the signal is already aborted", async () => {
|
||||||
|
const response = {
|
||||||
|
ok: true,
|
||||||
|
status: 200,
|
||||||
|
blob: vi.fn().mockResolvedValue(blob),
|
||||||
|
};
|
||||||
|
|
||||||
|
vi.stubGlobal("fetch", vi.fn().mockResolvedValue(response));
|
||||||
|
|
||||||
|
const { loadSourceBitmap } = await importSubject();
|
||||||
|
const controller = new AbortController();
|
||||||
|
controller.abort();
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
loadSourceBitmap("https://cdn.example.com/source.png", {
|
||||||
|
signal: controller.signal,
|
||||||
|
}),
|
||||||
|
).rejects.toMatchObject({ name: "AbortError" });
|
||||||
|
|
||||||
|
expect(fetch).not.toHaveBeenCalled();
|
||||||
|
expect(response.blob).not.toHaveBeenCalled();
|
||||||
|
expect(createImageBitmap).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
await expect(loadSourceBitmap("https://cdn.example.com/source.png")).resolves.toBe(bitmap);
|
||||||
|
|
||||||
|
expect(fetch).toHaveBeenCalledTimes(1);
|
||||||
|
expect(response.blob).toHaveBeenCalledTimes(1);
|
||||||
|
expect(createImageBitmap).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
it("lets a later consumer succeed after an earlier caller aborts", async () => {
|
it("lets a later consumer succeed after an earlier caller aborts", async () => {
|
||||||
const responseDeferred = createDeferred<{
|
const responseDeferred = createDeferred<{
|
||||||
ok: boolean;
|
ok: boolean;
|
||||||
|
|||||||
Reference in New Issue
Block a user