From f4af3fe701b175d73e5c5a82eeaf55ab9d6b214a Mon Sep 17 00:00:00 2001 From: daiwei Date: Tue, 19 Dec 2023 09:58:13 +0800 Subject: [PATCH 1/2] fix(compile-core): reuse analyzed scope variables if they are already present on node --- packages/compiler-core/src/babelUtils.ts | 38 ++++++++++++++++-------- 1 file changed, 26 insertions(+), 12 deletions(-) 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) } From bad5af107b8f5b9441b28b4aadaaed2d59850cad Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 19 Dec 2023 18:01:00 +0800 Subject: [PATCH 2/2] test: add test case --- .../__tests__/compileTemplate.spec.ts | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) 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