From 05948689b4865af1e8ab4a535f11044ee4d86bbf Mon Sep 17 00:00:00 2001 From: Nibu Date: Mon, 9 Nov 2026 23:08:48 +0000 Subject: [PATCH] Scene: a throwing ray-march createScene goes to onCompileFail create() called the ray-march createScene after the try, so a throw while building it escaped onCompileFail and the CSS ground was never kept. The call now sits inside the try with the other styles. Co-Authored-By: Claude Sonnet 5.5 --- src/app/features/scene/index.test.ts | 15 +++++++++++++++ src/app/features/scene/index.ts | 11 ++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/app/features/scene/index.test.ts b/src/app/features/scene/index.test.ts index 23c6b297..b6fcf2a7 100644 --- a/src/app/features/scene/index.test.ts +++ b/src/app/features/scene/index.test.ts @@ -239,4 +239,19 @@ describe('startBackgroundScene follows the sky state', () => { await flush(); expect(createScene).toHaveBeenCalledOnce(); }); + + it('keeps the ground and reports a ray-march scene that throws while being created', async () => { + const boom = new Error('shader link failed'); + createScene.mockImplementation(() => { + throw boom; + }); + const onCompileFail = vi.fn(); + const scene = await startBackgroundScene({ ...config, style: 'raymarch' }, caps, { + canvas, + onCompileFail, + }); + expect(scene).toBeNull(); + expect(onCompileFail).toHaveBeenCalledOnce(); + expect(onCompileFail).toHaveBeenCalledWith(boom); + }); }); diff --git a/src/app/features/scene/index.ts b/src/app/features/scene/index.ts index bc041672..4e1db231 100644 --- a/src/app/features/scene/index.ts +++ b/src/app/features/scene/index.ts @@ -21,12 +21,11 @@ async function create( options: StartOptions & { tier: SceneTier; debug?: boolean }, state: SkyState ): Promise { - let createScene: (o: SceneOptions) => Scene | null; try { // Loaded here, with the scenes, so the main chunk does not carry the terrain sky or the baked tables. const { ridgeSkyFor, terrainSkyFor } = await import('./skyForState'); - if (config?.style === 'raymarch') createScene = (await import('./Scene')).createScene; - else if (config?.style === 'terrain') { + if (config?.style === 'raymarch') return (await import('./Scene')).createScene(options); + if (config?.style === 'terrain') { const { createTerrainScene } = await import('./terrain/Terrain'); const sky = terrainSkyFor(state); const scene = createTerrainScene({ ...options, ...sky }); @@ -34,15 +33,13 @@ async function create( if (scene) return scene; const { createTerrainSkyScene } = await import('./terrain/TerrainSky2D'); return createTerrainSkyScene({ ...options, ...sky }); - } else { - const { createRidgeScene } = await import('./ridge/Ridge'); - return createRidgeScene({ ...options, sky: ridgeSkyFor(state) }); } + const { createRidgeScene } = await import('./ridge/Ridge'); + return createRidgeScene({ ...options, sky: ridgeSkyFor(state) }); } catch (e) { options.onCompileFail?.(e instanceof Error ? e : new Error(String(e))); return null; } - return createScene(options); } /**