mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 11:24:00 +00:00
fix(director): discard an asset cancelled during reader cleanup
The finally block awaits reader.cancel(), so a cancel arriving there still let the bytes return. Rechecks the signal after cleanup, with a test that keeps the caller's abort reason, and wraps the current-state note.
This commit is contained in:
1 parent
d42f5d4fd2
commit
bf4edb5bdb
3 files changed
+42
-1
No files matched your search
@@ -396,7 +396,9 @@ and geographic placement remain distinct; Stop/replacement releases resources.
|
|||||||
Import acquires nothing. See [data packs](DIRECTOR-DATA-PACKS.md). Existing scene
|
Import acquires nothing. See [data packs](DIRECTOR-DATA-PACKS.md). Existing scene
|
||||||
content, assets and credit remain unchanged.
|
content, assets and credit remain unchanged.
|
||||||
|
|
||||||
The asset directory source rejects with the caller's abort reason if cancellation arrives during any read, including the final one.
|
The asset directory source rejects with the caller's abort reason if
|
||||||
|
cancellation arrives during any read, including the final one, or while the
|
||||||
|
reader is being released.
|
||||||
|
|
||||||
Director version-4 documents add named geographic anchors and optional explicit
|
Director version-4 documents add named geographic anchors and optional explicit
|
||||||
camera moves with easing, duration and holds. Playback and seek share one
|
camera moves with easing, duration and holds. Playback and seek share one
|
||||||
|
|||||||
@@ -40,3 +40,40 @@ test('cancellation during the terminating read cannot return a scene asset', asy
|
|||||||
assert.equal(released, 1);
|
assert.equal(released, 1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('cancellation during reader cleanup cannot return a scene asset', async () => {
|
||||||
|
const controller = new AbortController();
|
||||||
|
const reason = new DOMException('scene changed', 'AbortError');
|
||||||
|
let released = 0;
|
||||||
|
const source = createAssetDirectorySource({
|
||||||
|
baseUrl: 'https://fixture.example/assets/',
|
||||||
|
fetchImpl: async () => ({
|
||||||
|
ok: true,
|
||||||
|
headers: new Headers(),
|
||||||
|
body: {
|
||||||
|
getReader() {
|
||||||
|
let reads = 0;
|
||||||
|
return {
|
||||||
|
async read() {
|
||||||
|
reads++;
|
||||||
|
return reads === 1
|
||||||
|
? { done: false, value: new Uint8Array([1]) }
|
||||||
|
: { done: true };
|
||||||
|
},
|
||||||
|
async cancel() {
|
||||||
|
controller.abort(reason);
|
||||||
|
},
|
||||||
|
releaseLock() {
|
||||||
|
released++;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
await assert.rejects(
|
||||||
|
source({ path: 'scene.bin', signal: controller.signal }),
|
||||||
|
(error) => error === reason,
|
||||||
|
);
|
||||||
|
assert.equal(released, 1);
|
||||||
|
});
|
||||||
@@ -51,6 +51,8 @@ export function createAssetDirectorySource({
|
|||||||
await reader.cancel().catch(() => {});
|
await reader.cancel().catch(() => {});
|
||||||
reader.releaseLock();
|
reader.releaseLock();
|
||||||
}
|
}
|
||||||
|
// Cleanup awaits too; a cancel during it must still discard the asset.
|
||||||
|
signal?.throwIfAborted();
|
||||||
const bytes = new Uint8Array(length);
|
const bytes = new Uint8Array(length);
|
||||||
let offset = 0;
|
let offset = 0;
|
||||||
for (const chunk of chunks) {
|
for (const chunk of chunks) {
|
||||||
|
|||||||
Reference in new issue
Block a user