Skip to content

Commit

Permalink
fix(compile-sfc): fix identifier prefixing edge case caused by reused…
Browse files Browse the repository at this point in the history
… AST (#9867)

close #9853
close #9863
  • Loading branch information
edison1105 authored Dec 19, 2023
1 parent 1d79b64 commit eb51b23
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 12 deletions.
38 changes: 26 additions & 12 deletions packages/compiler-core/src/babelUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,24 @@ export function walkIdentifiers(
// mark property in destructure pattern
;(node as any).inPattern = true
} else if (isFunctionType(node)) {
// walk function expressions and add its arguments to known identifiers
// so that we don't prefix them
walkFunctionParams(node, id => markScopeIdentifier(node, id, knownIds))
if (node.scopeIds) {
node.scopeIds.forEach(id => markKnownIds(id, knownIds))
} else {
// walk function expressions and add its arguments to known identifiers
// so that we don't prefix them
walkFunctionParams(node, id =>
markScopeIdentifier(node, id, knownIds)
)
}
} else if (node.type === 'BlockStatement') {
// #3445 record block-level local variables
walkBlockDeclarations(node, id =>
markScopeIdentifier(node, id, knownIds)
)
if (node.scopeIds) {
node.scopeIds.forEach(id => markKnownIds(id, knownIds))
} else {
// #3445 record block-level local variables
walkBlockDeclarations(node, id =>
markScopeIdentifier(node, id, knownIds)
)
}
}
},
leave(node: Node & { scopeIds?: Set<string> }, parent: Node | undefined) {
Expand Down Expand Up @@ -227,6 +237,14 @@ export function extractIdentifiers(
return nodes
}

function markKnownIds(name: string, knownIds: Record<string, number>) {
if (name in knownIds) {
knownIds[name]++
} else {
knownIds[name] = 1
}
}

function markScopeIdentifier(
node: Node & { scopeIds?: Set<string> },
child: Identifier,
Expand All @@ -236,11 +254,7 @@ function markScopeIdentifier(
if (node.scopeIds && node.scopeIds.has(name)) {
return
}
if (name in knownIds) {
knownIds[name]++
} else {
knownIds[name] = 1
}
markKnownIds(name, knownIds)
;(node.scopeIds || (node.scopeIds = new Set())).add(name)
}

Expand Down
30 changes: 30 additions & 0 deletions packages/compiler-sfc/__tests__/compileTemplate.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
SFCTemplateCompileOptions
} from '../src/compileTemplate'
import { parse, SFCTemplateBlock } from '../src/parse'
import { compileScript } from '../src'

function compile(opts: Omit<SFCTemplateCompileOptions, 'id'>) {
return compileTemplate({
Expand Down Expand Up @@ -397,6 +398,35 @@ test('dynamic v-on + static v-on should merged', () => {
expect(result.code).toMatchSnapshot()
})

// #9853 regression found in Nuxt tests
// walkIdentifiers can get called multiple times on the same node
// due to #9729 calling it during SFC template usage check.
// conditions needed:
// 1. `<script setup lang="ts">`
// 2. Has import
// 3. inlineTemplate: false
// 4. AST being reused
test('prefixing edge case for reused AST', () => {
const src = `
<script setup lang="ts">
import { Foo } from './foo'
</script>
<template>
{{ list.map((t, index) => ({ t: t })) }}
</template>
`
const { descriptor } = parse(src)
// compileScript triggers importUsageCheck
compileScript(descriptor, { id: 'xxx' })
const { code } = compileTemplate({
id: 'xxx',
filename: 'test.vue',
ast: descriptor.template!.ast,
source: descriptor.template!.content
})
expect(code).not.toMatch(`_ctx.t`)
})

interface Pos {
line: number
column: number
Expand Down

0 comments on commit eb51b23

Please sign in to comment.