mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +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
|
||||
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
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
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(() => {});
|
||||
reader.releaseLock();
|
||||
}
|
||||
// Cleanup awaits too; a cancel during it must still discard the asset.
|
||||
signal?.throwIfAborted();
|
||||
const bytes = new Uint8Array(length);
|
||||
let offset = 0;
|
||||
for (const chunk of chunks) {
|
||||
|
||||
Reference in new issue
Block a user