fix(director): keep a falsy phase error over a release failure

runError doubled as the failure flag, so a phase that threw a falsy
value was still masked by a final release error (ianblenke's nit).
Track failure with a boolean and cover it with a test. Make the
changelog fragment a wrapped bullet like the other fragments.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Said TurkseverandClaude Opus 5.5 committed 2026-10-19 14:27:25 +01:00
1 parent d64cd1dc6f
commit 76199c07ee
3 files changed
+29 -4

No files matched your search

@@ -1 +1,4 @@
Director clock listeners, interaction observers and scene release failures no longer leave the director inconsistent, and a phase error is kept when cleanup also fails (deepeshbind, #1014).
- Director clock listeners, interaction observers and scene release failures
no longer leave the director inconsistent: each scene is released once, and
a phase error is kept (with the release failure logged) when cleanup also
fails (deepeshbind, #1014).
+3 -3
View File
@@ -54,7 +54,7 @@ export async function playSceneQueue(
const cancelled = () => Boolean(token.cancelled || token.signal?.aborted);
let activeScene = null;
let completedShots = 0;
let runError = null;
let runFailed = false;
try {
if (!queue.length || cancelled()) {
return {
@@ -86,7 +86,7 @@ export async function playSceneQueue(
if (!cancelled()) await adapter.complete?.();
return { status: cancelled() ? 'cancelled' : 'completed', completedShots };
} catch (error) {
runError = error;
runFailed = true;
throw error;
} finally {
if (releaseOnFinish && activeScene) {
@@ -95,7 +95,7 @@ export async function playSceneQueue(
try {
await adapter.releaseScene(toRelease);
} catch (error) {
if (runError) {
if (runFailed) {
console.warn('[Scenes] Scene release failed:', error);
} else {
throw error;
+22
View File
@@ -239,3 +239,25 @@ test('a failing inter-scene release releases the active scene only once', async
);
assert.deepEqual(released, ['a']);
});
test('a falsy phase failure is still preserved over a release failure', async () => {
const releaseError = new Error('release failed');
const origWarn = console.warn;
console.warn = () => {};
try {
const f = fixture({
travel: async () => {
throw undefined;
},
releaseScene: async () => {
throw releaseError;
},
});
await assert.rejects(
playSceneQueue(buildPlaybackQueue(scenes, 'a', { single: true }), f),
(error) => error === undefined,
);
} finally {
console.warn = origWarn;
}
});