From 0854113c28c95b1198d91d7871048c826b9b8354 Mon Sep 17 00:00:00 2001 From: Johnson Chu Date: Sat, 6 Dec 2025 04:27:23 +0800 Subject: [PATCH] fix(language-core): AST fault tolerance for key binding on template --- .../lib/virtualCode/normalize.ts | 39 ++++++++++++++++++- .../tsc/passedFixtures/vue3/#4539/main.vue | 5 +++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 test-workspace/tsc/passedFixtures/vue3/#4539/main.vue diff --git a/packages/language-core/lib/virtualCode/normalize.ts b/packages/language-core/lib/virtualCode/normalize.ts index e378066d98..a111d0dad9 100644 --- a/packages/language-core/lib/virtualCode/normalize.ts +++ b/packages/language-core/lib/virtualCode/normalize.ts @@ -19,7 +19,7 @@ export function normalizeTemplateAST(root: CompilerDOM.RootNode) { expressionPlugins: ['typescript'], }; - for (const { children } of forEachElementNode(root)) { + for (const { children, codegenNode, props } of forEachElementNode(root)) { for (let i = 0; i < children.length; i++) { const child = children[i]!; if (child.type !== CompilerDOM.NodeTypes.ELEMENT) { @@ -37,6 +37,43 @@ export function normalizeTemplateAST(root: CompilerDOM.RootNode) { continue; } } + // #4539 + if ( + codegenNode + && 'props' in codegenNode + && codegenNode.props + && 'properties' in codegenNode.props + ) { + for (const p of codegenNode.props.properties) { + if ( + p.key.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION + && p.key.content === 'key' + && !p.key.isHandlerKey + && !p.key.loc.source + && p.value.type === CompilerDOM.NodeTypes.SIMPLE_EXPRESSION + && p.value.constType === CompilerDOM.ConstantTypes.NOT_CONSTANT + ) { + const contentBeforeValue = root.loc.source.slice(0, p.value.loc.start.offset); + const argOffset = contentBeforeValue.lastIndexOf('key'); + props.push({ + type: CompilerDOM.NodeTypes.DIRECTIVE, + name: 'bind', + exp: p.value, + loc: p.loc, + arg: { + ...p.key, + loc: { + start: { line: -1, column: -1, offset: argOffset }, + end: { line: -1, column: -1, offset: argOffset + 'key'.length }, + source: 'key', + }, + }, + modifiers: [], + }); + break; + } + } + } } } diff --git a/test-workspace/tsc/passedFixtures/vue3/#4539/main.vue b/test-workspace/tsc/passedFixtures/vue3/#4539/main.vue new file mode 100644 index 0000000000..1351329a9f --- /dev/null +++ b/test-workspace/tsc/passedFixtures/vue3/#4539/main.vue @@ -0,0 +1,5 @@ +