From 6c3d0a503e52593af6c320ab5fdd8027d64b07de Mon Sep 17 00:00:00 2001 From: Gregor Becker Date: Sun, 19 Jul 2026 23:28:47 +0200 Subject: [PATCH] fix(pinia-orm): fall back to strong refs when WeakRef is unavailable The default query cache crashed in environments without WeakRef support like Cloudflare Workers. The cache now degrades to holding values strongly instead of throwing. fixes #1949 --- packages/pinia-orm/src/cache/WeakCache.ts | 24 +++++++++++++++++-- .../tests/unit/cache/Weakcache.spec.ts | 15 +++++++++++- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/packages/pinia-orm/src/cache/WeakCache.ts b/packages/pinia-orm/src/cache/WeakCache.ts index fa2adfb4b..bd735b179 100644 --- a/packages/pinia-orm/src/cache/WeakCache.ts +++ b/packages/pinia-orm/src/cache/WeakCache.ts @@ -1,8 +1,28 @@ +interface ValueRef { + deref(): V | undefined +} + +/** + * Fallback for environments without WeakRef support (e.g. Cloudflare + * Workers). Values are held strongly instead of crashing. + */ +class StrongRef implements ValueRef { + #value: V + + constructor (value: V) { + this.#value = value + } + + deref (): V { + return this.#value + } +} + export class WeakCache implements Map { // @ts-expect-error dont know readonly [Symbol.toStringTag]: string - #map = new Map>() + #map = new Map>() has (key: K) { return !!(this.#map.has(key) && this.#map.get(key)?.deref()) @@ -25,7 +45,7 @@ export class WeakCache implements Map { } set (key: K, value: V) { - this.#map.set(key, new WeakRef(value)) + this.#map.set(key, typeof WeakRef === 'undefined' ? new StrongRef(value) : new WeakRef(value)) return this } diff --git a/packages/pinia-orm/tests/unit/cache/Weakcache.spec.ts b/packages/pinia-orm/tests/unit/cache/Weakcache.spec.ts index c37c4d5cb..2f3aa2da5 100644 --- a/packages/pinia-orm/tests/unit/cache/Weakcache.spec.ts +++ b/packages/pinia-orm/tests/unit/cache/Weakcache.spec.ts @@ -1,4 +1,4 @@ -import { describe, expect, it } from 'vitest' +import { describe, expect, it, vi } from 'vitest' import { WeakCache } from '../../../src/cache/WeakCache' @@ -72,4 +72,17 @@ describe('unit/support/Weakcache', () => { cache.clear() expect(cache.size).toEqual(0) }) + + it('falls back to strong references when WeakRef is not available', () => { + vi.stubGlobal('WeakRef', undefined) + + const fallbackCache = new WeakCache() + fallbackCache.set('key1', data) + + expect(fallbackCache.get('key1')).toEqual(data) + expect(fallbackCache.has('key1')).toBeTruthy() + expect([...fallbackCache.values()]).toEqual([data]) + + vi.unstubAllGlobals() + }) })