From 2a3e23bf19d962686dd06e2e777f13e3079637be Mon Sep 17 00:00:00 2001 From: Mikalai Silivonik Date: Thu, 2 Apr 2026 23:21:56 -0400 Subject: [PATCH 1/2] fix: clear lens cache on re-bootstrap The lens cache retained references from the old kit's lensRepository after re-bootstrap, causing fetchLens to return stale objects. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/CameraKitProvider.test.tsx | 56 ++++++++++++++++++++++++++++++++++ src/CameraKitProvider.tsx | 4 +++ 2 files changed, 60 insertions(+) diff --git a/src/CameraKitProvider.test.tsx b/src/CameraKitProvider.test.tsx index 9d39150..ea82ecd 100644 --- a/src/CameraKitProvider.test.tsx +++ b/src/CameraKitProvider.test.tsx @@ -382,6 +382,62 @@ describe("CameraKitProvider", () => { expect(result.current.lenses).toHaveLength(2); }); + it("should clear lens cache on re-bootstrap", async () => { + const mockLens = { id: "lens-1", groupId: "group-1" } as Lens; + (mockKit.lensRepository.loadLens as any).mockResolvedValue(mockLens); + + const mockKit2 = { + destroy: jest.fn().mockResolvedValue(undefined), + createSession: jest.fn().mockResolvedValue(mockSession), + lensRepository: { + loadLens: jest.fn().mockResolvedValue(mockLens), + loadLensGroups: jest.fn(), + }, + } as any; + + mockBootstrapCameraKit.mockReset().mockResolvedValueOnce(mockKit).mockResolvedValueOnce(mockKit2); + + let stabilityKey = "key-1"; + const wrapper = ({ children }: { children: React.ReactNode }) => ( + + {children} + + ); + + const { result, rerender } = renderHook(() => useCameraKit(), { wrapper }); + + await waitFor(() => { + expect(result.current.sdkStatus).toBe("ready"); + }); + + // Fetch a lens — populates the cache + await act(async () => { + await result.current.fetchLens("lens-1", "group-1"); + }); + + expect(mockKit.lensRepository.loadLens).toHaveBeenCalledTimes(1); + expect(result.current.lenses).toHaveLength(1); + + // Trigger re-bootstrap by changing stabilityKey + stabilityKey = "key-2"; + rerender(); + + await waitFor(() => { + expect(result.current.sdkStatus).toBe("ready"); + expect(mockBootstrapCameraKit).toHaveBeenCalledTimes(2); + }); + + // Lenses state should have been cleared + expect(result.current.lenses).toHaveLength(0); + + // Fetch the same lens again — should NOT hit cache, should call new kit's loadLens + await act(async () => { + await result.current.fetchLens("lens-1", "group-1"); + }); + + expect(mockKit2.lensRepository.loadLens).toHaveBeenCalledWith("lens-1", "group-1"); + }); + it("should apply lens", async () => { const mockLens = { id: "lens-1", groupId: "group-1" } as Lens; (mockKit.lensRepository.loadLens as any).mockResolvedValue(mockLens); diff --git a/src/CameraKitProvider.tsx b/src/CameraKitProvider.tsx index 82d8045..720c42c 100644 --- a/src/CameraKitProvider.tsx +++ b/src/CameraKitProvider.tsx @@ -352,6 +352,10 @@ export const CameraKitProvider: React.FC = ({ const abortController = new AbortController(); const emit = eventFactoryRef.current?.(); + // Clear stale lens cache — the old kit's lensRepository is no longer valid. + lensCache.current.clear(); + setLenses([]); + setCameraKitState({ status: "initializing" }); emit?.({ kind: "bootstrap-attempt" }); log.info("bootstrap_attempt"); From 0de84dd9a4cd73c92766850b61e7167d7247f111 Mon Sep 17 00:00:00 2001 From: Mikalai Silivonik Date: Thu, 2 Apr 2026 23:40:00 -0400 Subject: [PATCH 2/2] Bumped version --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index af13290..e34b948 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@snap/react-camera-kit", - "version": "0.1.0", + "version": "0.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@snap/react-camera-kit", - "version": "0.1.0", + "version": "0.2.0", "license": "MIT", "dependencies": { "stable-hash": "^0.0.6" diff --git a/package.json b/package.json index 86f705c..1036be6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@snap/react-camera-kit", - "version": "0.1.0", + "version": "0.2.0", "description": "React Camera Kit for web applications", "type": "module", "main": "./dist/cjs/index.js",