mirror of
https://github.com/nuxt/nuxt.git
synced 2025-01-30 15:22:39 +00:00
fix(nuxt): deep clone extracted page meta (#30717)
This commit is contained in:
parent
09d8db5f2f
commit
cb7f30a1ea
@ -11,6 +11,7 @@ import { transform } from 'esbuild'
|
||||
import type { Property } from 'estree'
|
||||
import type { NuxtPage } from 'nuxt/schema'
|
||||
|
||||
import { klona } from 'klona'
|
||||
import { parseAndWalk, withLocations } from '../core/utils/parse'
|
||||
import { getLoader, uniqueBy } from '../core/utils'
|
||||
import { logger, toArray } from '../utils'
|
||||
@ -215,7 +216,7 @@ export async function getRouteMeta (contents: string, absolutePath: string, extr
|
||||
}
|
||||
|
||||
if (absolutePath in metaCache && metaCache[absolutePath]) {
|
||||
return metaCache[absolutePath]
|
||||
return klona(metaCache[absolutePath])
|
||||
}
|
||||
|
||||
const loader = getLoader(absolutePath)
|
||||
@ -314,7 +315,7 @@ export async function getRouteMeta (contents: string, absolutePath: string, extr
|
||||
}
|
||||
|
||||
metaCache[absolutePath] = extractedMeta
|
||||
return extractedMeta
|
||||
return klona(extractedMeta)
|
||||
}
|
||||
|
||||
const COLON_RE = /:/g
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { type MockedFunction, describe, expect, it, vi } from 'vitest'
|
||||
import { compileScript, parse } from '@vue/compiler-sfc'
|
||||
import * as Parser from 'acorn'
|
||||
import { klona } from 'klona'
|
||||
import { transform as esbuildTransform } from 'esbuild'
|
||||
import { PageMetaPlugin } from '../src/pages/plugins/page-meta'
|
||||
import { getRouteMeta, normalizeRoutes } from '../src/pages/utils'
|
||||
@ -8,6 +9,8 @@ import type { NuxtPage } from '../schema'
|
||||
|
||||
const filePath = '/app/pages/index.vue'
|
||||
|
||||
vi.mock('klona', { spy: true })
|
||||
|
||||
describe('page metadata', () => {
|
||||
it('should not extract metadata from empty files', async () => {
|
||||
expect(await getRouteMeta('', filePath)).toEqual({})
|
||||
@ -67,11 +70,20 @@ definePageMeta({ name: 'bar' })
|
||||
})
|
||||
|
||||
it('should use and invalidate cache', async () => {
|
||||
const _klona = klona as unknown as MockedFunction<typeof klona>
|
||||
_klona.mockImplementation(obj => obj)
|
||||
const fileContents = `<script setup>definePageMeta({ foo: 'bar' })</script>`
|
||||
const meta = await getRouteMeta(fileContents, filePath)
|
||||
expect(meta === await getRouteMeta(fileContents, filePath)).toBeTruthy()
|
||||
expect(meta === await getRouteMeta(fileContents, '/app/pages/other.vue')).toBeFalsy()
|
||||
expect(meta === await getRouteMeta('<template><div>Hi</div></template>' + fileContents, filePath)).toBeFalsy()
|
||||
_klona.mockReset()
|
||||
})
|
||||
|
||||
it('should not share state between page metadata', async () => {
|
||||
const fileContents = `<script setup>definePageMeta({ foo: 'bar' })</script>`
|
||||
const meta = await getRouteMeta(fileContents, filePath)
|
||||
expect(meta === await getRouteMeta(fileContents, filePath)).toBeFalsy()
|
||||
})
|
||||
|
||||
it('should extract serialisable metadata', async () => {
|
||||
|
@ -836,3 +836,41 @@ describe('pages:pathToNitroGlob', () => {
|
||||
expect(pathToNitroGlob(path)).to.equal(expected)
|
||||
})
|
||||
})
|
||||
|
||||
describe('page:extends', () => {
|
||||
const DYNAMIC_META_KEY = '__nuxt_dynamic_meta_key' as const
|
||||
it('should preserve distinct metadata for multiple routes referencing the same file', async () => {
|
||||
const files: NuxtPage[] = [
|
||||
{ path: 'home', file: `pages/index.vue` },
|
||||
{ path: 'home1', file: `pages/index.vue`, meta: { test: true } },
|
||||
{ path: 'home2', file: `pages/index.vue`, meta: { snap: true } },
|
||||
]
|
||||
const vfs = Object.fromEntries(
|
||||
files.map(file => [file.file, `
|
||||
<script setup lang="ts">
|
||||
definePageMeta({
|
||||
hello: 'world'
|
||||
})
|
||||
</script>
|
||||
`]),
|
||||
) as Record<string, string>
|
||||
await augmentPages(files, vfs)
|
||||
expect(files).toEqual([
|
||||
{
|
||||
path: 'home',
|
||||
file: `pages/index.vue`,
|
||||
meta: { [DYNAMIC_META_KEY]: new Set(['meta']) },
|
||||
},
|
||||
{
|
||||
path: 'home1',
|
||||
file: `pages/index.vue`,
|
||||
meta: { [DYNAMIC_META_KEY]: new Set(['meta']), test: true },
|
||||
},
|
||||
{
|
||||
path: 'home2',
|
||||
file: `pages/index.vue`,
|
||||
meta: { [DYNAMIC_META_KEY]: new Set(['meta']), snap: true },
|
||||
},
|
||||
])
|
||||
})
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user