diff --git a/packages/compiler-core/src/babelUtils.ts b/packages/compiler-core/src/babelUtils.ts index a9c1ebe9c32..c00c18b3fed 100644 --- a/packages/compiler-core/src/babelUtils.ts +++ b/packages/compiler-core/src/babelUtils.ts @@ -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 }, parent: Node | undefined) { @@ -227,6 +237,14 @@ export function extractIdentifiers( return nodes } +function markKnownIds(name: string, knownIds: Record) { + if (name in knownIds) { + knownIds[name]++ + } else { + knownIds[name] = 1 + } +} + function markScopeIdentifier( node: Node & { scopeIds?: Set }, child: Identifier, @@ -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) } diff --git a/packages/compiler-sfc/__tests__/compileTemplate.spec.ts b/packages/compiler-sfc/__tests__/compileTemplate.spec.ts index 95e1b7aa81a..26a8b573f4e 100644 --- a/packages/compiler-sfc/__tests__/compileTemplate.spec.ts +++ b/packages/compiler-sfc/__tests__/compileTemplate.spec.ts @@ -4,6 +4,7 @@ import { SFCTemplateCompileOptions } from '../src/compileTemplate' import { parse, SFCTemplateBlock } from '../src/parse' +import { compileScript } from '../src' function compile(opts: Omit) { return compileTemplate({ @@ -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. ` + + ` + 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