From fc5f3a8a4b1b1a5afce8de26c43620e3904bd3c7 Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Sat, 28 Dec 2024 12:47:46 +0200 Subject: [PATCH 1/3] fix: shouldHydrate error when null object is passed --- packages/pinia/src/store.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/pinia/src/store.ts b/packages/pinia/src/store.ts index a09196a4e5..c5410e5977 100644 --- a/packages/pinia/src/store.ts +++ b/packages/pinia/src/store.ts @@ -136,7 +136,10 @@ export function skipHydrate(obj: T): T { * @returns true if `obj` should be hydrated */ export function shouldHydrate(obj: any) { - return !isPlainObject(obj) || !obj.hasOwnProperty(skipHydrateSymbol) + return ( + !isPlainObject(obj) || + !Object.prototype.hasOwnProperty.call(obj, skipHydrateSymbol) + ) } const { assign } = Object From 15460d53e62c50dc11780ea5f87f69051ca56d16 Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Sat, 28 Dec 2024 13:42:17 +0200 Subject: [PATCH 2/3] test(nuxt): Add tests --- packages/nuxt/playground/pages/null-object-store.vue | 8 ++++++++ .../playground/stores/with-null-\316\277bject.ts" | 12 ++++++++++++ packages/nuxt/test/nuxt.spec.ts | 9 +++++++++ packages/pinia/__tests__/ssr.spec.ts | 7 +++++++ 4 files changed, 36 insertions(+) create mode 100644 packages/nuxt/playground/pages/null-object-store.vue create mode 100644 "packages/nuxt/playground/stores/with-null-\316\277bject.ts" diff --git a/packages/nuxt/playground/pages/null-object-store.vue b/packages/nuxt/playground/pages/null-object-store.vue new file mode 100644 index 0000000000..576c03db06 --- /dev/null +++ b/packages/nuxt/playground/pages/null-object-store.vue @@ -0,0 +1,8 @@ + + + diff --git "a/packages/nuxt/playground/stores/with-null-\316\277bject.ts" "b/packages/nuxt/playground/stores/with-null-\316\277bject.ts" new file mode 100644 index 0000000000..42db0adb85 --- /dev/null +++ "b/packages/nuxt/playground/stores/with-null-\316\277bject.ts" @@ -0,0 +1,12 @@ +export const useWithNullObjectStore = defineStore('with-null-object', () => { + return { + text: ref(Object.create(null)), + foo: ref('bar'), + } +}) + +if (import.meta.hot) { + import.meta.hot.accept( + acceptHMRUpdate(useWithNullObjectStore, import.meta.hot) + ) +} diff --git a/packages/nuxt/test/nuxt.spec.ts b/packages/nuxt/test/nuxt.spec.ts index 8bcbfccc05..76a9041e81 100644 --- a/packages/nuxt/test/nuxt.spec.ts +++ b/packages/nuxt/test/nuxt.spec.ts @@ -1,6 +1,7 @@ import { fileURLToPath } from 'node:url' import { describe, it, expect } from 'vitest' import { setup, $fetch } from '@nuxt/test-utils/e2e' +import exp from 'node:constants' describe('works with nuxt', async () => { await setup({ @@ -28,6 +29,14 @@ describe('works with nuxt', async () => { expect(html).toContain('Count: 101') }) + it('works with null objects', async () => { + expect(async () => { + const html = await $fetch('/null-object-store') + expect(html).toContain('null object') + expect(html).toContain('bar') + }).not.toThrow() + }) + it('drops state that is marked with skipHydrate', async () => { const html = await $fetch('/skip-hydrate') expect(html).not.toContain('I should not be serialized or hydrated') diff --git a/packages/pinia/__tests__/ssr.spec.ts b/packages/pinia/__tests__/ssr.spec.ts index 5f5a364d81..10fc66793d 100644 --- a/packages/pinia/__tests__/ssr.spec.ts +++ b/packages/pinia/__tests__/ssr.spec.ts @@ -152,6 +152,13 @@ describe('SSR', () => { expect(store.$state).toEqual({ start: 'start' }) }) + it('accepts a store with no null state', () => { + const pinia = createPinia() + pinia.state.value.a = Object.create(null) + const store = defineStore('a', {})(pinia) + expect(store.$state).toEqual({}) + }) + describe('Setup Store', () => { const useStore = defineStore('main', () => { const count = ref(0) From 87734004a605e982a32d20cb4ad0e363fc2ff73a Mon Sep 17 00:00:00 2001 From: Vaggelis Yfantis Date: Sat, 28 Dec 2024 13:50:50 +0200 Subject: [PATCH 3/3] ci: Trigger CI