mirror of
https://github.com/nuxt/nuxt.git
synced 2025-01-30 23:32:38 +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 { Property } from 'estree'
|
||||||
import type { NuxtPage } from 'nuxt/schema'
|
import type { NuxtPage } from 'nuxt/schema'
|
||||||
|
|
||||||
|
import { klona } from 'klona'
|
||||||
import { parseAndWalk, withLocations } from '../core/utils/parse'
|
import { parseAndWalk, withLocations } from '../core/utils/parse'
|
||||||
import { getLoader, uniqueBy } from '../core/utils'
|
import { getLoader, uniqueBy } from '../core/utils'
|
||||||
import { logger, toArray } from '../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]) {
|
if (absolutePath in metaCache && metaCache[absolutePath]) {
|
||||||
return metaCache[absolutePath]
|
return klona(metaCache[absolutePath])
|
||||||
}
|
}
|
||||||
|
|
||||||
const loader = getLoader(absolutePath)
|
const loader = getLoader(absolutePath)
|
||||||
@ -314,7 +315,7 @@ export async function getRouteMeta (contents: string, absolutePath: string, extr
|
|||||||
}
|
}
|
||||||
|
|
||||||
metaCache[absolutePath] = extractedMeta
|
metaCache[absolutePath] = extractedMeta
|
||||||
return extractedMeta
|
return klona(extractedMeta)
|
||||||
}
|
}
|
||||||
|
|
||||||
const COLON_RE = /:/g
|
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 { compileScript, parse } from '@vue/compiler-sfc'
|
||||||
import * as Parser from 'acorn'
|
import * as Parser from 'acorn'
|
||||||
|
import { klona } from 'klona'
|
||||||
import { transform as esbuildTransform } from 'esbuild'
|
import { transform as esbuildTransform } from 'esbuild'
|
||||||
import { PageMetaPlugin } from '../src/pages/plugins/page-meta'
|
import { PageMetaPlugin } from '../src/pages/plugins/page-meta'
|
||||||
import { getRouteMeta, normalizeRoutes } from '../src/pages/utils'
|
import { getRouteMeta, normalizeRoutes } from '../src/pages/utils'
|
||||||
@ -8,6 +9,8 @@ import type { NuxtPage } from '../schema'
|
|||||||
|
|
||||||
const filePath = '/app/pages/index.vue'
|
const filePath = '/app/pages/index.vue'
|
||||||
|
|
||||||
|
vi.mock('klona', { spy: true })
|
||||||
|
|
||||||
describe('page metadata', () => {
|
describe('page metadata', () => {
|
||||||
it('should not extract metadata from empty files', async () => {
|
it('should not extract metadata from empty files', async () => {
|
||||||
expect(await getRouteMeta('', filePath)).toEqual({})
|
expect(await getRouteMeta('', filePath)).toEqual({})
|
||||||
@ -67,11 +70,20 @@ definePageMeta({ name: 'bar' })
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should use and invalidate cache', async () => {
|
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 fileContents = `<script setup>definePageMeta({ foo: 'bar' })</script>`
|
||||||
const meta = await getRouteMeta(fileContents, filePath)
|
const meta = await getRouteMeta(fileContents, filePath)
|
||||||
expect(meta === await getRouteMeta(fileContents, filePath)).toBeTruthy()
|
expect(meta === await getRouteMeta(fileContents, filePath)).toBeTruthy()
|
||||||
expect(meta === await getRouteMeta(fileContents, '/app/pages/other.vue')).toBeFalsy()
|
expect(meta === await getRouteMeta(fileContents, '/app/pages/other.vue')).toBeFalsy()
|
||||||
expect(meta === await getRouteMeta('<template><div>Hi</div></template>' + fileContents, filePath)).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 () => {
|
it('should extract serialisable metadata', async () => {
|
||||||
|
@ -836,3 +836,41 @@ describe('pages:pathToNitroGlob', () => {
|
|||||||
expect(pathToNitroGlob(path)).to.equal(expected)
|
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