fix(nuxt): use node location instead of range for route meta property extraction (#30447)

This commit is contained in:
Matej Černý 2025-01-04 22:14:55 +01:00 committed by Daniel Roe
parent e786d79bee
commit b00264cd7c
No known key found for this signature in database
GPG Key ID: CBC814C393D93268
2 changed files with 22 additions and 8 deletions

View File

@ -11,7 +11,7 @@ import { transform } from 'esbuild'
import type { Property } from 'estree'
import type { NuxtPage } from 'nuxt/schema'
import { parseAndWalk } from '../core/utils/parse'
import { parseAndWalk, withLocations } from '../core/utils/parse'
import { getLoader, uniqueBy } from '../core/utils'
import { logger, toArray } from '../utils'
@ -247,8 +247,10 @@ export async function getRouteMeta (contents: string, absolutePath: string, extr
const property = pageMetaArgument.properties.find((property): property is Property => property.type === 'Property' && property.key.type === 'Identifier' && property.key.name === key)
if (!property) { continue }
if (property.value.type === 'ObjectExpression') {
const valueString = js.code.slice(property.value.range![0], property.value.range![1])
const propertyValue = withLocations(property.value)
if (propertyValue.type === 'ObjectExpression') {
const valueString = js.code.slice(propertyValue.start, propertyValue.end)
try {
extractedMeta[key] = JSON.parse(runInNewContext(`JSON.stringify(${valueString})`, {}))
} catch {
@ -258,9 +260,9 @@ export async function getRouteMeta (contents: string, absolutePath: string, extr
}
}
if (property.value.type === 'ArrayExpression') {
if (propertyValue.type === 'ArrayExpression') {
const values: string[] = []
for (const element of property.value.elements) {
for (const element of propertyValue.elements) {
if (!element) {
continue
}
@ -275,12 +277,12 @@ export async function getRouteMeta (contents: string, absolutePath: string, extr
continue
}
if (property.value.type !== 'Literal' || (typeof property.value.value !== 'string' && typeof property.value.value !== 'boolean')) {
if (propertyValue.type !== 'Literal' || (typeof propertyValue.value !== 'string' && typeof propertyValue.value !== 'boolean')) {
logger.debug(`Skipping extraction of \`${key}\` metadata as it is not a string literal or array of string literals (reading \`${absolutePath}\`).`)
dynamicProperties.add(key)
continue
}
extractedMeta[key] = property.value.value
extractedMeta[key] = propertyValue.value
}
for (const property of pageMetaArgument.properties) {

View File

@ -78,7 +78,6 @@ definePageMeta({ name: 'bar' })
const meta = await getRouteMeta(`
<script setup>
definePageMeta({
name: 'some-custom-name',
path: '/some-custom-path',
validate: () => true,
middleware: [
@ -87,19 +86,32 @@ definePageMeta({ name: 'bar' })
otherValue: {
foo: 'bar',
},
// 'name', 'props' and 'alias' are part of 'defaultExtractionKeys'; they're extracted from the component, so we should test the AST walking for different value types
name: 'some-custom-name',
props: {
foo: 'bar',
},
alias: ['/alias'],
})
</script>
`, filePath)
expect(meta).toMatchInlineSnapshot(`
{
"alias": [
"/alias",
],
"meta": {
"__nuxt_dynamic_meta_key": Set {
"props",
"meta",
},
},
"name": "some-custom-name",
"path": "/some-custom-path",
"props": {
"foo": "bar",
},
}
`)
})