diff --git a/package.json b/package.json index 87d06126f0..d025a86dc0 100644 --- a/package.json +++ b/package.json @@ -71,6 +71,7 @@ "changelogen": "0.5.5", "consola": "3.2.3", "cssnano": "7.0.4", + "destr": "^2.0.3", "devalue": "5.0.0", "eslint": "9.8.0", "eslint-plugin-no-only-tests": "3.1.0", diff --git a/packages/nuxt/src/app/composables/cookie.ts b/packages/nuxt/src/app/composables/cookie.ts index 7ba5f71fcb..fa93422de9 100644 --- a/packages/nuxt/src/app/composables/cookie.ts +++ b/packages/nuxt/src/app/composables/cookie.ts @@ -40,6 +40,7 @@ export function useCookie (name: string, _opts?: export function useCookie (name: string, _opts: CookieOptions & { readonly: true }): Readonly> export function useCookie (name: string, _opts?: CookieOptions): CookieRef { const opts = { ...CookieDefaults, ..._opts } + opts.filter ??= key => key === name const cookies = readRawCookies(opts) || {} let delay: number | undefined diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e2bc105d6a..e0d5a0f4ed 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -86,6 +86,9 @@ importers: cssnano: specifier: 7.0.4 version: 7.0.4(postcss@8.4.41) + destr: + specifier: ^2.0.3 + version: 2.0.3 devalue: specifier: 5.0.0 version: 5.0.0 diff --git a/test/nuxt/composables.test.ts b/test/nuxt/composables.test.ts index 5f5a0f1fe2..9fcb97dedd 100644 --- a/test/nuxt/composables.test.ts +++ b/test/nuxt/composables.test.ts @@ -2,6 +2,7 @@ import { describe, expect, it, vi } from 'vitest' import { defineEventHandler } from 'h3' +import { destr } from 'destr' import { mount } from '@vue/test-utils' import { mountSuspended, registerEndpoint } from '@nuxt/test-utils/runtime' @@ -691,6 +692,38 @@ describe('useCookie', () => { expect(computedVal.value).toBe(0) }) + it('cookie decode function should be invoked once', () => { + // Pre-set cookies + document.cookie = 'foo=Foo' + document.cookie = 'bar=%7B%22s2%22%3A0%7D' + document.cookie = 'baz=%7B%22s2%22%3A0%7D' + + let barCallCount = 0 + const bazCookie = useCookie<{ s2: number }>('baz', { + default: () => ({ s2: -1 }), + decode (value) { + barCallCount++ + return destr(decodeURIComponent(value)) + }, + }) + bazCookie.value.s2++ + expect(bazCookie.value.s2).toEqual(1) + expect(barCallCount).toBe(1) + + let quxCallCount = 0 + const quxCookie = useCookie<{ s3: number }>('qux', { + default: () => ({ s3: -1 }), + filter: key => key === 'bar' || key === 'baz', + decode (value) { + quxCallCount++ + return destr(decodeURIComponent(value)) + }, + }) + quxCookie.value.s3++ + expect(quxCookie.value.s3).toBe(0) + expect(quxCallCount).toBe(2) + }) + it('should not watch custom cookie refs when shallow', () => { for (const value of ['shallow', false] as const) { const user = useCookie('shallowUserInfo', {