From af32c8f72a4fa7e21edb866a26b7c32a78c1bb04 Mon Sep 17 00:00:00 2001 From: Lao Chou Date: Thu, 21 May 2026 19:04:34 +0800 Subject: [PATCH] fix: ignore cachebust_origin in obj loader cache key --- src/hooks/use-global-obj-loader.ts | 33 ++++++++++++++----- tests/use-global-obj-loader-cache-key.test.ts | 32 ++++++++++++++++++ 2 files changed, 56 insertions(+), 9 deletions(-) create mode 100644 tests/use-global-obj-loader-cache-key.test.ts diff --git a/src/hooks/use-global-obj-loader.ts b/src/hooks/use-global-obj-loader.ts index 69422095..c72c3446 100644 --- a/src/hooks/use-global-obj-loader.ts +++ b/src/hooks/use-global-obj-loader.ts @@ -20,6 +20,20 @@ if (typeof window !== "undefined" && !window.TSCIRCUIT_OBJ_LOADER_CACHE) { window.TSCIRCUIT_OBJ_LOADER_CACHE = new Map() } +export function getObjLoaderCacheKey(url: string): string { + try { + const base = + typeof window !== "undefined" ? window.location.href : undefined + const parsedUrl = new URL(url, base) + parsedUrl.searchParams.delete("cachebust_origin") + return parsedUrl.href + } catch { + return url + .replace(/([?&])cachebust_origin=[^&#]*/g, "$1") + .replace(/[?&]$/, "") + } +} + export function useGlobalObjLoader( url: string | null, ): Object3D | null | Error { @@ -28,21 +42,22 @@ export function useGlobalObjLoader( useEffect(() => { if (!url) return - const cleanUrl = url.replace(/&cachebust_origin=$/, "") + const fetchUrl = url.replace(/&cachebust_origin=$/, "") + const cacheKey = getObjLoaderCacheKey(fetchUrl) const cache = window.TSCIRCUIT_OBJ_LOADER_CACHE let hasUrlChanged = false async function loadAndParseObj() { try { - if (cleanUrl.endsWith(".wrl")) { - return await loadVrml(cleanUrl) + if (fetchUrl.endsWith(".wrl")) { + return await loadVrml(fetchUrl) } - const response = await fetch(cleanUrl) + const response = await fetch(fetchUrl) if (!response.ok) { throw new Error( - `Failed to fetch "${cleanUrl}": ${response.status} ${response.statusText}`, + `Failed to fetch "${fetchUrl}": ${response.status} ${response.statusText}`, ) } const text = await response.text() @@ -79,8 +94,8 @@ export function useGlobalObjLoader( } function loadUrl() { - if (cache.has(cleanUrl)) { - const cacheItem = cache.get(cleanUrl)! + if (cache.has(cacheKey)) { + const cacheItem = cache.get(cacheKey)! if (cacheItem.result) { // If we have a result, clone it return Promise.resolve(cacheItem.result.clone()) @@ -97,10 +112,10 @@ export function useGlobalObjLoader( // If the result is an Error, return it return result } - cache.set(cleanUrl, { ...cache.get(cleanUrl)!, result }) + cache.set(cacheKey, { ...cache.get(cacheKey)!, result }) return result }) - cache.set(cleanUrl, { promise, result: null }) + cache.set(cacheKey, { promise, result: null }) return promise } diff --git a/tests/use-global-obj-loader-cache-key.test.ts b/tests/use-global-obj-loader-cache-key.test.ts new file mode 100644 index 00000000..6961d5c1 --- /dev/null +++ b/tests/use-global-obj-loader-cache-key.test.ts @@ -0,0 +1,32 @@ +import { expect, test } from "bun:test" +import { getObjLoaderCacheKey } from "../src/hooks/use-global-obj-loader" + +test("removes cachebust_origin from the OBJ loader cache key", () => { + expect( + getObjLoaderCacheKey( + "https://modelcdn.tscircuit.com/easyeda_models/download?uuid=model-1&pn=C123&cachebust_origin=http%3A%2F%2Flocalhost%3A6006", + ), + ).toBe( + "https://modelcdn.tscircuit.com/easyeda_models/download?uuid=model-1&pn=C123", + ) +}) + +test("keeps non-cachebust query parameters in the OBJ loader cache key", () => { + expect( + getObjLoaderCacheKey( + "https://modelcdn.tscircuit.com/easyeda_models/download?cachebust_origin=https%3A%2F%2Fexample.com&uuid=model-1&pn=C123", + ), + ).toBe( + "https://modelcdn.tscircuit.com/easyeda_models/download?uuid=model-1&pn=C123", + ) +}) + +test("keeps URLs unchanged when no cachebust_origin parameter is present", () => { + expect( + getObjLoaderCacheKey( + "https://modelcdn.tscircuit.com/easyeda_models/download?uuid=model-1&pn=C123", + ), + ).toBe( + "https://modelcdn.tscircuit.com/easyeda_models/download?uuid=model-1&pn=C123", + ) +})